Dizinler, tüm veritabanları için uygun veri modellemenin önemli bir parçasıdır ve DynamoDB de bir istisna değildir. DynamoDB'nin ikincil dizinleri, verileriniz için yeni erişim modellerini etkinleştiren güçlü bir araçtır.
Bu yazıda DynamoDB ikincil dizinlerine bakacağız. Öncelikle DynamoDB hakkında nasıl düşünmemiz gerektiği ve ikincil dizinlerin çözdüğü sorunlar hakkında bazı kavramsal noktalarla başlayacağız. Ardından ikincil dizinleri etkili bir şekilde kullanmaya yönelik bazı pratik ipuçlarına bakacağız. Son olarak, ikincil dizinleri ne zaman kullanmanız gerektiği ve ne zaman başka çözümler aramanız gerektiği konusunda bazı düşüncelerle bitireceğiz.
Başlayalım.
DynamoDB nedir ve DynamoDB ikincil dizinleri nelerdir?
İkincil dizinlerin kullanım örneklerine ve en iyi uygulamalarına geçmeden önce, DynamoDB ikincil dizinlerinin ne olduğunu anlamalıyız. Bunu yapmak için DynamoDB'nin nasıl çalıştığını biraz anlamamız gerekiyor.
Bu, DynamoDB'nin temel düzeyde anlaşıldığını varsayar. İkincil dizinleri anlamak için bilmeniz gereken temel noktaları ele alacağız ancak DynamoDB'de yeniyseniz daha temel bir girişle başlamak isteyebilirsiniz.
DynamoDB Hakkında Bilmeniz Gereken Minimum Bilgiler
DynamoDB benzersiz bir veritabanıdır. OLTP iş yükleri için tasarlanmıştır; bu, yüksek hacimli küçük işlemleri gerçekleştirmek için harika olduğu anlamına gelir; alışveriş sepetine ürün eklemek, bir videoyu beğenmek veya Reddit'e yorum eklemek gibi şeyleri düşünün. Bu şekilde MySQL, PostgreSQL, MongoDB veya Cassandra gibi kullanmış olabileceğiniz diğer veritabanlarıyla benzer uygulamaları işleyebilir.
DynamoDB'nin en önemli vaadi , her ölçekte tutarlı performansın garantisidir. Tablonuzda ister 1 megabayt veri, ister 1 petabayt veri bulunsun, DynamoDB, OLTP benzeri istekleriniz için aynı gecikme süresine sahip olmak ister. Bu çok önemli; veri miktarını veya eşzamanlı isteklerin sayısını artırdığınızda birçok veritabanında performans düşüşü görülecektir. Ancak bu garantilerin sağlanması bazı ödünleşimler gerektirir ve DynamoDB'nin, onu etkili bir şekilde kullanmak için anlamanız gereken bazı benzersiz özellikleri vardır.
Öncelikle DynamoDB, verilerinizi birden fazla bölüme yayarak veritabanlarınızı yatay olarak ölçeklendirir. Bu bölümler kullanıcı olarak size görünmez ancak DynamoDB'nin çalışma şeklinin temelini oluştururlar. Tablonuz için bir birincil anahtar belirleyeceksiniz ("bölüm anahtarı" adı verilen tek bir öğe veya bölüm anahtarı ile sıralama anahtarının birleşimi) ve DynamoDB, verilerinizin hangi bölümde yer aldığını belirlemek için bu birincil anahtarı kullanacaktır. . Yaptığınız herhangi bir istek, isteği hangi bölümün işlemesi gerektiğini belirleyecek bir istek yönlendiricisinden geçecektir. Bu bölümler küçüktür (genellikle 10 GB veya daha azdır), dolayısıyla bağımsız olarak taşınabilir, bölünebilir, çoğaltılabilir ve başka şekilde yönetilebilirler.
Parçalama yoluyla yatay ölçeklenebilirlik ilginçtir ancak kesinlikle DynamoDB'ye özgü değildir. Hem ilişkisel hem de ilişkisel olmayan diğer birçok veritabanı, yatay olarak ölçeklendirmek için parçalamayı kullanır. Ancak DynamoDB'ye özgü olan şey, verilerinize erişmek için sizi birincil anahtarınızı kullanmaya nasıl zorladığıdır. DynamoDB, isteklerinizi bir dizi sorguya çeviren bir sorgu planlayıcı kullanmak yerine sizi verilerinize erişmek için birincil anahtarınızı kullanmaya zorlar . Esasen verileriniz için doğrudan adreslenebilir bir dizin alıyorsunuz.
DynamoDB API'si bunu yansıtıyor. Tek tek öğeler üzerinde ( GetItem
, PutItem
, UpdateItem
, DeleteItem
) tek tek öğeleri okumanıza, yazmanıza ve silmenize olanak tanıyan bir dizi işlem vardır. Ayrıca, aynı bölüm anahtarıyla birden fazla öğeyi almanıza olanak tanıyan bir Query
işlemi de vardır. Bileşik birincil anahtara sahip bir tablonuz varsa, aynı bölüm anahtarına sahip öğeler aynı bölümde birlikte gruplandırılacaktır. Sıralama anahtarına göre sıralanacaklar ve "Bir Kullanıcı için En Son Siparişleri Getir" veya "Bir IoT Cihazı için Son 10 Sensör Okumasını Getir" gibi kalıpları yönetmenize olanak tanıyacaklar.
Örneğin, Kullanıcılar tablosuna sahip bir SaaS uygulamasını hayal edelim. Tüm Kullanıcılar tek bir Kuruluşa aittir. Aşağıdaki gibi görünen bir tablomuz olabilir:
'Kuruluş' bölüm anahtarı ve 'Kullanıcı adı' sıralama anahtarından oluşan bileşik bir birincil anahtar kullanıyoruz. Bu, bireysel bir Kullanıcıyı Kuruluşunu ve Kullanıcı Adını sağlayarak getirmek veya güncellemek için işlemler yapmamıza olanak tanır. Ayrıca bir Query
işlemine yalnızca Kuruluşu sağlayarak tek bir Kuruluşun tüm Kullanıcılarını da getirebiliriz.
İkincil dizinler nedir ve nasıl çalışırlar?
Bazı temel bilgileri aklımızda tutarak şimdi ikincil dizinlere bakalım. İkincil indekslere olan ihtiyacı anlamanın en iyi yolu onların çözdüğü sorunu anlamaktır. DynamoDB'nin verilerinizi birincil anahtarınıza göre nasıl bölümlediğini ve verilerinize erişmek için sizi birincil anahtarı kullanmaya nasıl zorladığını gördük. Bazı erişim modelleri için bunların hepsi iyi ve güzel, peki ya verilerinize farklı bir şekilde erişmeniz gerekiyorsa?
Yukarıdaki örneğimizde, kuruluşları ve kullanıcı adlarına göre eriştiğimiz bir kullanıcı tablomuz vardı. Ancak tek bir kullanıcıyı e-posta adresinden de getirmemiz gerekebilir. Bu model, DynamoDB'nin bizi zorladığı birincil anahtar erişim modeliyle uymuyor. Tablomuz farklı niteliklere göre bölümlendiğinden verilerimize istediğimiz şekilde erişmenin net bir yolu yoktur. Tam tablo taraması yapabiliriz ancak bu yavaş ve verimsizdir. Verilerimizi farklı bir birincil anahtarla ayrı bir tabloya kopyalayabiliriz ancak bu karmaşıklığı artırır.
İkincil dizinlerin devreye girdiği yer burasıdır. İkincil dizin, temel olarak verilerinizin farklı bir birincil anahtarla tam olarak yönetilen bir kopyasıdır. Dizinin birincil anahtarını bildirerek tablonuzda ikincil bir dizin belirleyeceksiniz. Tablonuza yazma işlemleri geldikçe DynamoDB, verileri otomatik olarak ikincil dizininize kopyalar.
Not *: Bu bölümdeki her şey global ikincil dizinler için geçerlidir. DynamoDB ayrıca biraz farklı olan yerel ikincil dizinler de sağlar. Neredeyse her durumda küresel bir ikincil dizin isteyeceksiniz. Farklılıklar hakkında daha fazla ayrıntı için küresel veya yerel ikincil dizin seçme hakkındaki bu makaleye göz atın.*
Bu durumda tablomuza "E-posta" bölüm anahtarına sahip ikincil bir dizin ekleyeceğiz. İkincil dizin aşağıdaki gibi görünecektir:
Bunun aynı veri olduğuna dikkat edin, farklı bir birincil anahtarla yeniden düzenlendi. Artık bir kullanıcıyı e-posta adresine göre verimli bir şekilde arayabiliriz.
Bazı açılardan bu, diğer veritabanlarındaki indekslere çok benzer. Her ikisi de belirli bir öznitelikteki aramalar için optimize edilmiş bir veri yapısı sağlar. Ancak DynamoDB'nin ikincil dizinleri birkaç temel açıdan farklıdır.
İlki ve en önemlisi, DynamoDB'nin dizinleri ana tablonuzdan tamamen farklı bölümlerde bulunur. DynamoDB her aramanın verimli ve öngörülebilir olmasını istiyor ve doğrusal yatay ölçeklendirme sağlamak istiyor. Bunu yapmak için, verilerinizi sorgulamak için kullanacağınız niteliklere göre yeniden donanımlandırması gerekir.
Diğer dağıtılmış veritabanlarında genellikle verilerinizi ikincil dizin için yeniden düzenlemezler. Genellikle yalnızca parçadaki tüm veriler için ikincil dizini korurlar. Bununla birlikte, dizinleriniz parça anahtarını kullanmıyorsa, parça anahtarı olmayan bir sorgunun, aradığınız verileri bulmak için tüm parçalar arasında bir dağılım toplama işlemi yapması gerekeceğinden, verilerinizi yatay olarak ölçeklendirmenin bazı avantajlarından mahrum kalırsınız. Arıyorum.
DynamoDB'nin ikincil dizinlerinin farklı olmasının ikinci bir yolu da (genellikle) öğenin tamamını ikincil dizine kopyalamalarıdır. İlişkisel bir veritabanındaki dizinler için, dizin genellikle dizine eklenen öğenin birincil anahtarına yönelik bir işaretçi içerir. Dizinde ilgili bir kaydı bulduktan sonra, veritabanının öğenin tamamını alması gerekecektir. DynamoDB'nin ikincil dizinleri ana tablodan farklı düğümlerde olduğundan, ağın orijinal öğeye geri dönmesini önlemek istiyorlar. Bunun yerine, okuma işleminizi gerçekleştirmek için ihtiyaç duyduğunuz kadar veriyi ikincil dizine kopyalayacaksınız.
DynamoDB'deki ikincil dizinler güçlüdür ancak bazı sınırlamaları vardır. Öncelikle salt okunurdurlar; doğrudan ikincil bir dizine yazamazsınız. Bunun yerine, siz ana tablonuza yazacaksınız ve DynamoDB, ikincil dizininize kopyalama işlemini gerçekleştirecektir. İkincisi, ikincil dizinlerinize yazma işlemleri için sizden ücret alınır. Bu nedenle, tablonuza ikincil bir dizin eklemek genellikle tablonuzun toplam yazma maliyetini iki katına çıkaracaktır.
İkincil dizinleri kullanmaya ilişkin ipuçları
Artık ikincil indekslerin ne olduğunu ve nasıl çalıştığını anladığımıza göre, onları nasıl etkili bir şekilde kullanabileceğimizden bahsedelim. İkincil dizinler güçlü bir araçtır ancak kötüye kullanılabilirler. İkincil dizinleri etkili bir şekilde kullanmaya yönelik bazı ipuçlarını burada bulabilirsiniz.
İkincil dizinlerde salt okunur kalıplara sahip olmaya çalışın
İlk ipucu açık görünüyor; ikincil dizinler yalnızca okumalar için kullanılabilir, bu nedenle ikincil dizinlerinizde salt okunur kalıplara sahip olmayı hedeflemelisiniz! Ama yine de bu hatayı her zaman görüyorum. Geliştiriciler önce ikincil bir dizinden okuyacak, ardından ana tabloya yazacaklar. Bu, ekstra maliyete ve ekstra gecikmeye neden olur ve önceden planlama yaparak çoğu zaman bunu önleyebilirsiniz.
DynamoDB veri modelleme hakkında herhangi bir şey okuduysanız muhtemelen öncelikle erişim düzenlerinizi düşünmeniz gerektiğini biliyorsunuzdur. İlk önce normalleştirilmiş tablolar tasarladığınız ve ardından bunları birleştirmek için sorgular yazdığınız ilişkisel bir veritabanına benzemez. DynamoDB'de uygulamanızın gerçekleştireceği eylemleri düşünmeli, ardından tablolarınızı ve dizinlerinizi bu eylemleri destekleyecek şekilde tasarlamalısınız.
Masamı tasarlarken öncelikle yazma tabanlı erişim modelleriyle başlamayı seviyorum. Yazılarımda genellikle bir tür kısıtlamayı koruyorum - bir kullanıcı adının benzersizliği veya bir gruptaki maksimum üye sayısı. Tablomu bunu basitleştirecek şekilde, ideal olarak DynamoDB İşlemlerini kullanmadan veya yarış koşullarına tabi olabilecek okuma-değiştir-yazma modelini kullanmadan tasarlamak istiyorum.
Bunlar üzerinde çalışırken, genellikle öğenizi tanımlamanın yazma kalıplarınızla eşleşen 'birincil' bir yolu olduğunu göreceksiniz. Bu sizin birincil anahtarınız olacak. Daha sonra, ikincil dizinlerle ek ikincil okuma kalıpları eklemek kolaydır.
Daha önceki Kullanıcı örneğimizde, her Kullanıcı isteği büyük olasılıkla Kuruluşu ve Kullanıcı Adını içerecektir. Bu, bireysel Kullanıcı kaydına bakmamı ve ayrıca Kullanıcı tarafından yapılan belirli eylemleri yetkilendirmemi sağlayacak. E-posta adresi araması, 'şifremi unuttum' akışı veya 'kullanıcı arama' akışı gibi daha az belirgin erişim kalıpları için olabilir. Bunlar salt okunur kalıplardır ve ikincil bir dizinle iyi uyum sağlarlar.
Anahtarlarınız değiştirilebilir olduğunda ikincil dizinleri kullanın
İkincil dizinleri kullanmanın ikinci ipucu, bunları erişim kalıplarınızdaki değiştirilebilir değerler için kullanmaktır. Önce bunun arkasındaki mantığı anlayalım, sonra da geçerli olduğu durumlara bakalım.
DynamoDB, mevcut bir öğeyi UpdateItem
işlemiyle güncellemenize olanak tanır. Ancak bir güncellemedeki bir öğenin birincil anahtarını değiştiremezsiniz . Birincil anahtar, bir öğenin benzersiz tanımlayıcısıdır ve birincil anahtarı değiştirmek temelde yeni bir öğe oluşturmaktır. Mevcut bir öğenin birincil anahtarını değiştirmek istiyorsanız eski öğeyi silmeniz ve yeni bir öğe oluşturmanız gerekir. Bu iki aşamalı süreç daha yavaş ve maliyetlidir. Çoğu zaman önce orijinal öğeyi okumanız, ardından orijinal öğeyi silmek ve aynı istekte yeni bir öğe oluşturmak için bir işlem kullanmanız gerekir.
Öte yandan, ikincil bir dizinin birincil anahtarında bu değiştirilebilir değere sahipseniz DynamoDB, çoğaltma sırasında bu silme + oluşturma işlemini sizin için gerçekleştirecektir. Değeri değiştirmek için basit bir UpdateItem
isteği gönderebilirsiniz; gerisini DynamoDB halledecektir.
Bu modelin iki ana durumda ortaya çıktığını görüyorum. İlki ve en yaygın olanı, sıralamak istediğiniz değişken bir özelliğe sahip olduğunuz zamandır. Buradaki kanonik örnekler, insanların sürekli olarak puan topladığı bir oyun için veya en son güncellenen öğeleri ilk önce görüntülemek istediğiniz, sürekli güncellenen bir öğe listesi için bir liderlik tablosudur. Dosyalarınızı 'son değiştirilme'ye göre sıralayabileceğiniz Google Drive gibi bir şey düşünün.
Bunun ortaya çıktığı ikinci bir model, filtrelemek istediğiniz değişken bir özelliğe sahip olduğunuz zamandır. Burada, bir kullanıcının sipariş geçmişine sahip bir e-ticaret mağazası düşünebilirsiniz. Kullanıcının siparişlerini duruma göre filtrelemesine izin vermek isteyebilirsiniz; 'gönderildi' veya 'teslim edildi' olan tüm siparişlerimi bana gösterin. Tam eşleşme filtrelemesine izin vermek için bunu bölüm anahtarınıza veya sıralama anahtarınızın başlangıcına yerleştirebilirsiniz. Öğenin durumu değiştikçe durum özelliğini güncelleyebilir ve öğeleri ikincil dizininizde doğru şekilde gruplamak için DynamoDB'ye güvenebilirsiniz.
Her iki durumda da, bu değiştirilebilir özelliği ikincil endeksinize taşımak, zamandan ve paradan tasarruf etmenizi sağlayacaktır. Okuma-değiştirme-yazma düzeninden kaçınarak zamandan tasarruf edeceksiniz ve işlemin ekstra yazma maliyetlerinden kaçınarak paradan tasarruf edeceksiniz.
Ek olarak, bu modelin önceki ipucuna çok iyi uyduğunu unutmayın. Bir öğeyi, önceki puanı, önceki durumu veya en son güncellenme zamanı gibi değişken özelliklere göre yazmak üzere tanımlamanız pek olası değildir. Bunun yerine, kullanıcının kimliği, sipariş kimliği veya dosyanın kimliği gibi daha kalıcı bir değerle güncelleme yapacaksınız. Daha sonra, değişken özniteliğe göre sıralamak ve filtrelemek için ikincil dizini kullanacaksınız.
'Yağ' bölümünden kaçının
Yukarıda DynamoDB'nin verilerinizi birincil anahtara göre bölümlere ayırdığını gördük. DynamoDB bu bölümleri küçük (10 GB veya daha az) tutmayı amaçlar ve DynamoDB'nin ölçeklenebilirliğinin avantajlarından yararlanmak için istekleri bölümlerinize yaymayı hedeflemelisiniz.
Bu genellikle bölüm anahtarınızda yüksek kardinaliteli bir değer kullanmanız gerektiği anlamına gelir. Kullanıcı adı, sipariş kimliği veya sensör kimliği gibi bir şey düşünün. Bu nitelikler için çok sayıda değer vardır ve DynamoDB, trafiği bölümlerinize yayabilir.
Çoğu zaman, insanların bu prensibi ana tablolarında anladıklarını, ancak daha sonra ikincil dizinlerinde bunu tamamen unuttuklarını görüyorum. Çoğu zaman, bir tür ürün için tüm masada sipariş vermek isterler. Kullanıcıları alfabetik olarak almak istiyorlarsa, tüm kullanıcıların bölüm anahtarı olarak USERS
ve sıralama anahtarı olarak kullanıcı adının bulunduğu ikincil bir dizin kullanırlar. Veya, bir e-ticaret mağazasındaki en son siparişlerin sıralanmasını istiyorlarsa, tüm siparişlerin bölüm anahtarı olarak ORDERS
ve sıralama anahtarı olarak zaman damgasına sahip olduğu ikincil bir dizin kullanacaklardır.
Bu model, DynamoDB bölümü aktarım hızı sınırlarına yaklaşmayacağınız trafiğin az olduğu uygulamalarda işe yarayabilir ancak yüksek trafikli bir uygulama için tehlikeli bir modeldir. Tüm trafiğiniz tek bir fiziksel bölüme yönlendirilebilir ve bu bölüm için yazma verimi sınırlarına hızla ulaşabilirsiniz.
Dahası ve en tehlikelisi, bu durum ana masanızda sorunlara neden olabilir. İkincil dizininiz çoğaltma sırasında yazma kısıtlamasına maruz kalıyorsa çoğaltma kuyruğu yedeklenir. Bu kuyruk çok fazla yedeklenirse DynamoDB ana tablonuzdaki yazma işlemlerini reddetmeye başlayacaktır.
Bu size yardımcı olmak için tasarlanmıştır - DynamoDB, ikincil dizininizin eskimesini sınırlamak ister, böylece büyük miktarda gecikmeye sahip bir ikincil dizine girmenizi engeller. Ancak hiç beklemediğiniz bir anda karşınıza çıkan şaşırtıcı bir durum da olabilir.
Seyrek dizinleri genel filtre olarak kullanma
İnsanlar genellikle ikincil dizinleri, tüm verilerini yeni bir birincil anahtarla çoğaltmanın bir yolu olarak düşünürler. Ancak tüm verilerinizin ikincil bir dizinde yer almasına ihtiyacınız yoktur. Dizinin anahtar şemasıyla eşleşmeyen bir öğeniz varsa dizine çoğaltılmaz.
Bu, verileriniz üzerinde genel bir filtre sağlamak için gerçekten yararlı olabilir. Bunun için kullandığım standart örnek bir mesaj gelen kutusudur. Ana tablonuzda, belirli bir kullanıcıya ait tüm mesajları, oluşturuldukları zamana göre sıralanmış olarak saklayabilirsiniz.
Ama eğer benim gibiyseniz, gelen kutunuzda çok fazla mesaj var. Ayrıca, okunmamış mesajları birine geri dönüş yapılması için küçük hatırlatıcılar gibi bir 'yapılacaklar' listesi olarak değerlendirebilirsiniz. Bu nedenle genellikle gelen kutumda yalnızca okunmamış mesajları görmek istiyorum.
unread == true
olan bu genel filtreyi sağlamak için ikincil dizininizi kullanabilirsiniz. Belki de ikincil dizin bölümü anahtarınız ${userId}#UNREAD
gibi bir şeydir ve sıralama anahtarı da iletinin zaman damgasıdır. İletiyi başlangıçta oluşturduğunuzda, ikincil dizin bölümü anahtar değerini içerecek ve dolayısıyla okunmamış iletilerin ikincil dizinine kopyalanacaktır. Daha sonra kullanıcı mesajı okuduğunda status
READ
olarak değiştirebilir ve ikincil dizin bölümü anahtarı değerini silebilirsiniz. DynamoDB daha sonra onu ikincil dizininizden kaldıracaktır.
Bu numarayı her zaman kullanıyorum ve oldukça etkili. Ayrıca, seyrek bir endeks paradan tasarruf etmenizi sağlayacaktır. İletilerin okunmasına ilişkin herhangi bir güncelleme ikincil dizine kopyalanmayacak ve yazma maliyetlerinden tasarruf edeceksiniz.
Dizin boyutunu ve/veya yazma işlemlerini azaltmak için ikincil dizin projeksiyonlarınızı daraltın
Son ipucumuz için, bir önceki noktayı biraz daha ileri götürelim. Öğenin dizin için birincil anahtar öğelerine sahip olmaması durumunda DynamoDB'nin ikincil dizininize bir öğe eklemeyeceğini gördük. Bu numara yalnızca birincil anahtar öğeler için değil aynı zamanda verilerdeki anahtar olmayan nitelikler için de kullanılabilir!
İkincil dizin oluşturduğunuzda, ana tablodan hangi niteliklerin ikincil dizine dahil edilmesini istediğinizi belirtebilirsiniz. Buna endeksin projeksiyonu denir. Ana tablodaki tüm nitelikleri, yalnızca birincil anahtar niteliklerini veya niteliklerin bir alt kümesini dahil etmeyi seçebilirsiniz.
Tüm özellikleri ikincil dizininize dahil etmek cazip gelse de, bu maliyetli bir hata olabilir. Ana tablonuza yansıtılan bir özelliğin değerini değiştiren her yazma işleminin ikincil dizininize kopyalanacağını unutmayın. Tam projeksiyonlu tek bir ikincil dizin, tablonuzun yazma maliyetlerini etkili bir şekilde iki katına çıkarır. Her ek ikincil dizin, yazma maliyetlerinizi 1/N + 1
artırır; burada N
yenisinden önceki ikincil dizinlerin sayısıdır.
Ayrıca yazma maliyetleriniz öğenizin boyutuna göre hesaplanır. Tablonuza yazılan her 1 KB veri bir WCU kullanır. 4 KB'lık bir öğeyi ikincil dizininize kopyalıyorsanız, hem ana tablonuzdaki hem de ikincil dizininizdeki 4 WCU'nun tamamını ödeyeceksiniz.
Dolayısıyla ikincil endeks projeksiyonlarınızı daraltarak tasarruf etmenin iki yolu vardır. İlk olarak, belirli yazma işlemlerinden tamamen kaçınabilirsiniz. İkincil dizin projeksiyonunuzdaki herhangi bir özniteliğe dokunmayan bir güncelleme işleminiz varsa DynamoDB, ikincil dizininize yazma işlemini atlayacaktır. İkinci olarak, ikincil dizininize çoğaltılan yazma işlemleri için, çoğaltılan öğenin boyutunu azaltarak paradan tasarruf edebilirsiniz.
Bu, doğru olması zor bir denge olabilir. İkincil endeks projeksiyonları, endeks oluşturulduktan sonra değiştirilemez. İkincil dizininizde ek özelliklere ihtiyacınız olduğunu fark ederseniz, yeni projeksiyonla yeni bir dizin oluşturmanız ve ardından eski dizini silmeniz gerekir.
İkincil bir dizin kullanmalı mısınız?
Artık ikincil dizinlerle ilgili bazı pratik tavsiyeleri araştırdığımıza göre, bir adım geriye gidelim ve daha temel bir soru soralım: İkincil dizin kullanmalı mısınız?
Gördüğümüz gibi ikincil dizinler verilerinize farklı bir şekilde erişmenize yardımcı olur. Ancak bu, ek yazma maliyetine neden olur. Dolayısıyla ikincil indeksler için temel kuralım şudur:
Azalan okuma maliyetleri artan yazma maliyetlerinden daha ağır bastığında ikincil dizinleri kullanın.
Bunu söylediğinizde bu çok açık görünüyor, ancak modellik yaparken mantığa aykırı olabilir. Diğer yaklaşımları düşünmeden "İkincil dizine at" demek çok kolay görünüyor.
Bunu anlayabilmek için ikincil indekslerin anlamlı olmayabileceği iki duruma bakalım.
Küçük öğe koleksiyonlarında çok sayıda filtrelenebilir özellik
DynamoDB'de genellikle birincil anahtarlarınızın filtreleme işlemini sizin yerinize yapmasını istersiniz. DynamoDB'de bir Sorgu kullanıp uygulamamda kendi filtrelememi yaptığımda bu beni biraz rahatsız ediyor -- neden bunu birincil anahtara yerleştiremedim?
İçten gelen tepkime rağmen, verilerinizi aşırı okumak ve ardından uygulamanızı filtrelemek isteyebileceğiniz bazı durumlar vardır.
Bunu en sık göreceğiniz yer, kullanıcılarınız için verileriniz üzerinde birçok farklı filtre sağlamak istediğiniz ancak ilgili veri kümesinin sınırlı olduğu zamandır.
Bir antrenman takipçisi düşünün. Kullanıcıların antrenman türü, yoğunluk, süre, tarih vb. gibi birçok özelliğe göre filtreleme yapmasına izin vermek isteyebilirsiniz. Bununla birlikte, bir kullanıcının sahip olduğu antrenman sayısı yönetilebilir olacaktır; deneyimli bir kullanıcının bile 1000 antrenmanı aşması biraz zaman alacaktır. Tüm bu özelliklere indeksler koymak yerine, kullanıcının tüm antrenmanlarını alıp uygulamanızı filtreleyebilirsiniz.
Burası matematiği yapmanızı tavsiye ettiğim yer. DynamoDB, bu iki seçeneği hesaplamayı ve uygulamanız için hangisinin daha iyi çalışacağını anlamanızı kolaylaştırır.
Büyük öğe koleksiyonlarında çok sayıda filtrelenebilir özellik
Durumumuzu biraz değiştirelim; ya eşya koleksiyonumuz büyükse? Peki ya bir spor salonu için bir antrenman izleyicisi oluşturuyorsak ve spor salonu sahibinin, spor salonundaki tüm kullanıcılar için yukarıda bahsettiğimiz tüm özellikleri filtrelemesine izin vermek istiyorsak?
Bu durumu değiştirir. Artık her biri yüzlerce, hatta binlerce antrenman yapan yüzlerce, hatta binlerce kullanıcıdan bahsediyoruz. Tüm öğe koleksiyonunu aşırı okumak ve sonuçlar üzerinde geçici filtreleme yapmak mantıklı olmayacaktır.
Ancak ikincil indeksler de burada pek bir anlam ifade etmiyor. İkincil dizinler, ilgili filtrelerin mevcut olduğuna güvenebileceğiniz bilinen erişim modelleri için iyidir. Spor salonu sahibimizin, tümü isteğe bağlı olan çeşitli özelliklere göre filtreleme yapabilmesini istiyorsak, bunun işe yaraması için çok sayıda dizin oluşturmamız gerekir.
Sorgu planlayıcıların olası dezavantajlarından daha önce bahsetmiştik ama sorgu planlayıcıların iyi yanları da var. Daha esnek sorgulara izin vermenin yanı sıra, bu sorguları oluştururken birden çok dizinden alınan kısmi sonuçlara bakmak için dizin kesişimleri gibi şeyler de yapabilirler. Aynı şeyi DynamoDB ile de yapabilirsiniz, ancak bu, uygulamanızda birçok ileri geri hareketin yanı sıra bunu çözmek için bazı karmaşık uygulama mantıklarıyla sonuçlanacaktır.
Bu tür sorunlarla karşılaştığımda genellikle bu kullanım durumuna daha uygun bir araç ararım. Veri kümenizde esnek, ikincil dizin benzeri filtreleme sağlamak için Rockset ve Elasticsearch benim öncelikli önerilerimdir.
Çözüm
Bu yazıda DynamoDB ikincil dizinlerini öğrendik. Öncelikle DynamoDB'nin nasıl çalıştığını ve ikincil dizinlere neden ihtiyaç duyulduğunu anlamak için bazı kavramsal parçalara baktık. Ardından, ikincil dizinlerin etkili bir şekilde nasıl kullanılacağını anlamak ve onlara özgü tuhaflıkları öğrenmek için bazı pratik ipuçlarını inceledik. Son olarak, diğer yaklaşımları ne zaman kullanmanız gerektiğini görmek için ikincil dizinler hakkında nasıl düşüneceğimize baktık.
İkincil dizinler DynamoDB araç kutunuzdaki güçlü bir araçtır ancak sihirli bir değnek değildir. Tüm DynamoDB veri modellemesinde olduğu gibi, erişim modellerinizi dikkatli bir şekilde değerlendirdiğinizden ve başlamadan önce maliyetleri hesapladığınızdan emin olun.
Alex DeBrie'nin Rockset'te SQL Kullanan DynamoDB Filtreleme ve Toplama Sorguları adlı blogundan ikincil dizin benzeri filtreleme için Rockset'i nasıl kullanabileceğiniz hakkında daha fazla bilgi edinin.