Azure Cosmos DB'de dizine genel bakış

ŞUNLAR IÇIN GEÇERLIDIR: NoSQL MongoDB Cassandra Gremlin Masa

Azure Cosmos DB, şema veya dizin yönetimiyle uğraşmak zorunda kalmadan uygulamanızda yineleme yapmanızı sağlayan şemadan bağımsız bir veritabanıdır. Varsayılan olarak, Azure Cosmos DB herhangi bir şema tanımlamak veya ikincil dizinleri yapılandırmak zorunda kalmadan kapsayıcınızdaki tüm öğeler için her özelliği otomatik olarak dizinler.

Bu makalenin amacı Azure Cosmos DB'nin verileri nasıl dizine aldığını ve sorgu performansını geliştirmek için dizinleri nasıl kullandığını açıklamaktır. Dizin oluşturma ilkelerini özelleştirmeyi keşfetmeden önce bu bölümün üzerinden geçmeniz önerilir.

Öğelerden ağaçlara

Bir öğe kapsayıcıda her depolandığında, içeriği JSON belgesi olarak yansıtılır ve ardından ağaç gösterimine dönüştürülür. Bu dönüştürme, söz konusu öğenin her özelliğinin bir ağaçta düğüm olarak temsil olduğu anlamına gelir. Bir sahte kök düğüm, öğenin tüm birinci düzey özelliklerinin üst öğesi olarak oluşturulur. Yaprak düğümler, bir öğe tarafından taşınan gerçek skaler değerleri içerir.

Örneğin, şu öğeyi göz önünde bulundurun:

{
  "locations": [
    { "country": "Germany", "city": "Berlin" },
    { "country": "France", "city": "Paris" }
  ],
  "headquarters": { "country": "Belgium", "employees": 250 },
  "exports": [
    { "city": "Moscow" },
    { "city": "Athens" }
  ]
}

Bu ağaç örnek JSON öğesini temsil eder:

Ağaç olarak temsil edilen önceki JSON öğesinin diyagramı.

Dizilerin ağaçta nasıl kodlandığına dikkat edin: Bir dizideki her giriş, dizi içindeki girdinin diziniyle etiketlenmiş bir ara düğüm alır (0, 1 vb.).

Ağaçlardan özellik yollarına

Azure Cosmos DB'nin öğeleri ağaçlara dönüştürmesinin nedeni, sistemin bu ağaçlar içindeki yollarını kullanarak özelliklere başvurmasına izin vermesidir. Bir özelliğin yolunu almak için kök düğümden bu özelliğe ağaç geçişi yapabilir ve geçirilen her düğümün etiketlerini birleştirebiliriz.

Aşağıda, daha önce açıklanan örnek öğeden her özelliğin yolları verilmiştir:

  • /locations/0/country: "Almanya"
  • /locations/0/city: "Berlin"
  • /locations/1/country: "Fransa"
  • /locations/1/city: "Paris"
  • /headquarters/country: "Belçika"
  • /headquarters/employees: 250
  • /exports/0/city: "Moskova"
  • /exports/1/city: "Atina"

Azure Cosmos DB, bir öğe yazıldığında her özelliğin yolunu ve buna karşılık gelen değerini etkili bir şekilde dizinler.

Dizin türleri

Azure Cosmos DB şu anda üç tür dizini desteklemektedir. Dizin oluşturma ilkesini tanımlarken bu dizin türlerini yapılandırabilirsiniz.

Aralık Dizini

Aralık dizinleri sıralı ağaç benzeri bir yapıyı temel alır. Aralık dizin türü aşağıdakiler için kullanılır:

  • Eşitlik sorguları:

    SELECT * FROM container c WHERE c.property = 'value'
    
    SELECT * FROM c WHERE c.property IN ("value1", "value2", "value3")
    
  • Dizi öğesinde eşitlik eşleşmesi

    SELECT * FROM c WHERE ARRAY_CONTAINS(c.tags, "tag1")
    
  • Aralık sorguları:

    SELECT * FROM container c WHERE c.property > 'value'
    

    Not

    (, , <, >=, <=için !=çalışır>)

  • Bir özelliğin varlığı denetleniyor:

    SELECT * FROM c WHERE IS_DEFINED(c.property)
    
  • Dize sistemi işlevleri:

    SELECT * FROM c WHERE CONTAINS(c.property, "value")
    
    SELECT * FROM c WHERE STRINGEQUALS(c.property, "value")
    
  • ORDER BY Sorgu:

    SELECT * FROM container c ORDER BY c.property
    
  • JOIN Sorgu:

    SELECT child FROM container c JOIN child IN c.properties WHERE child = 'value'
    

Aralık dizinleri skaler değerlerde (dize veya sayı) kullanılabilir. Yeni oluşturulan kapsayıcıların varsayılan dizin oluşturma ilkesi tüm dizeler veya sayılar için aralık dizinlerini zorunlu tutar. Aralık dizinlerini yapılandırmayı öğrenmek için bkz . Aralık dizin oluşturma ilkesi örnekleri

Not

ORDER BY Tek bir özelliğe göre sipariş veren bir yan tümce her zaman bir aralık dizinine ihtiyaç duyar ve başvurduğunu yolun bir dizini yoksa başarısız olur. Benzer şekilde, birden çok özelliğe göre sıralanan bir ORDER BY sorgu her zaman bileşik dizine ihtiyaç duyar.

Uzamsal dizin

Uzamsal dizinler, noktalar, çizgiler, çokgenler ve çok kutuplu gibi jeo-uzamsal nesneler üzerinde verimli sorgular sağlar. Bu sorgular ST_DISTANCE, ST_WITHIN ST_INTERSECTS anahtar sözcükleri kullanır. Uzamsal dizin türünü kullanan bazı örnekler aşağıda verilmiştir:

  • Jeo-uzamsal uzaklık sorguları:

    SELECT * FROM container c WHERE ST_DISTANCE(c.property, { "type": "Point", "coordinates": [0.0, 10.0] }) < 40
    
  • Sorgular içinde jeo-uzamsal:

    SELECT * FROM container c WHERE ST_WITHIN(c.property, {"type": "Point", "coordinates": [0.0, 10.0] })
    
  • Jeo-uzamsal kesişme sorguları:

    SELECT * FROM c WHERE ST_INTERSECTS(c.property, { 'type':'Polygon', 'coordinates': [[ [31.8, -5], [32, -5], [31.8, -5] ]]  })  
    

Uzamsal dizinler doğru biçimlendirilmiş GeoJSON nesnelerinde kullanılabilir. Points, LineStrings, Polygons ve MultiPolygons şu anda desteklenmektedir. Uzamsal dizinleri yapılandırmayı öğrenmek için bkz . Uzamsal dizin oluşturma ilkesi örnekleri

Bileşik dizinler

Bileşik dizinler, birden çok alanda işlem gerçekleştirirken verimliliği artırır. Bileşik dizin türü aşağıdakiler için kullanılır:

  • ORDER BY birden çok özellik üzerinde sorgular:

    SELECT * FROM container c ORDER BY c.property1, c.property2
    
  • ve ORDER BYfiltreli sorgular. Filtre özelliği yan tümcesine ORDER BY eklenirse bu sorgular bileşik dizin kullanabilir.

    SELECT * FROM container c WHERE c.property1 = 'value' ORDER BY c.property1, c.property2
    
  • En az bir özelliğin eşitlik filtresi olduğu iki veya daha fazla özellikte filtre içeren sorgular

    SELECT * FROM container c WHERE c.property1 = 'value' AND c.property2 > 'value'
    

Bir filtre koşulu dizin türünden birini kullandığı sürece, sorgu altyapısı geri kalanını taramadan önce bunu değerlendirir. Örneğin, gibi bir SQL sorgunuz varsa SELECT * FROM c WHERE c.firstName = "Andrew" and CONTAINS(c.lastName, "Liu")

  • Yukarıdaki sorgu ilk olarak dizini kullanarak firstName = "Andrew" olan girdileri filtreleyecektir. Ardından, CONTAINS filtre koşulunu değerlendirmek için sonraki bir işlem hattından firstName = "Andrew" girdilerinin tümünü geçirir.

  • CONTAINS gibi tam tarama gerçekleştiren işlevleri kullanırken sorguları hızlandırabilir ve tam kapsayıcı taramalarından kaçınabilirsiniz. Bu sorguları hızlandırmak için dizini kullanan daha fazla filtre koşulu ekleyebilirsiniz. Filtre yan tümcelerinin sırası önemli değildir. Sorgu altyapısı hangi önkoşulların daha seçici olduğunu anlayıp sorguyu buna göre çalıştırır.

Bileşik dizinleri yapılandırmayı öğrenmek için bkz . Bileşik dizin oluşturma ilkesi örnekleri

Vektör dizinleri

Vektör dizinleri, sistem işlevini kullanarak VectorDistance vektör aramaları yaparken verimliliği artırır. Vektör dizinlerinden yararlanırken vektör aramalarında önemli ölçüde daha düşük gecikme süresi, daha yüksek aktarım hızı ve daha az RU tüketimi olacaktır. Vektör dizinlerini yapılandırmayı öğrenmek için bkz. vektör dizin oluşturma ilkesi örnekleri

  • ORDER BY vektör arama sorguları:

    SELECT c.name
    FROM c
    ORDER BY VectorDistance(c.vector1, c.vector2)
    
  • Vektör arama sorgularındaki benzerlik puanının projeksiyonu:

    SELECT c.name, VectorDistance(c.vector1, c.vector2) AS SimilarityScore
    FROM c
    ORDER BY VectorDistance(c.vector1, c.vector2)
    
  • Benzerlik puanındaki aralık filtreleri.

    SELECT c.name
    FROM c
    WHERE VectorDistance(c.vector1, c.vector2) > 0.8
    ORDER BY VectorDistance(c.vector1, c.vector2)
    

    Önemli

    Vektör dizinleri kapsayıcı oluşturma sırasında tanımlanmalıdır ve oluşturulduktan sonra değiştirilemez. Gelecek bir sürümde vektör dizinleri değiştirilebilir olacak.

Dizin kullanımı

Sorgu altyapısının sorgu filtrelerini en verimliden en az verimliye doğru sıralanmış olarak değerlendirebileceği beş yöntem vardır:

  • Dizin arama
  • Kesin dizin taraması
  • Genişletilmiş dizin taraması
  • Tam dizin taraması
  • Tam tarama

Özellik yollarını dizine aldığınızda, sorgu altyapısı dizini otomatik olarak mümkün olduğunca verimli bir şekilde kullanır. Yeni özellik yollarını dizine eklemenin yanı sıra sorguların dizini kullanma biçimini iyileştirmek için herhangi bir şey yapılandırmanız gerekmez. Sorgunun RU ücreti, hem dizin kullanımından gelen RU ücretinin hem de öğeleri yüklemenin RU ücretinin bir bileşimidir.

Azure Cosmos DB'de dizinlerin farklı kullanım yollarını özetleyen bir tablo aşağıdadır:

Dizin arama türü Açıklama Yaygın Örnekler Dizin kullanımından RU ücreti İşlemsel veri deposundan öğe yüklemeden RU ücretleri
Dizin arama Yalnızca gerekli dizine alınan değerleri okuma ve işlem veri deposundan yalnızca eşleşen öğeleri yükleme Eşitlik filtreleri, IN Eşitlik filtresi başına sabit Sorgu sonuçlarındaki öğe sayısına göre artar
Kesin dizin taraması Dizine alınan değerlerin ikili araması ve yalnızca işlem veri deposundan eşleşen öğeleri yükleme Aralık karşılaştırmaları (>, <, <=veya >=), StartsWith Dizin arama ile karşılaştırılabilir, dizine alınan özelliklerin kardinalitesine göre biraz artar Sorgu sonuçlarındaki öğe sayısına göre artar
Genişletilmiş dizin taraması Dizine alınan değerler için iyileştirilmiş arama (ancak ikili aramadan daha az verimli) ve işlem veri deposundan yalnızca eşleşen öğeleri yükleme StartsWith (büyük/küçük harfe duyarlı değil), StringEquals (büyük/küçük harfe duyarlı değil) Dizine alınan özelliklerin kardinalitesine göre biraz artar Sorgu sonuçlarındaki öğe sayısına göre artar
Tam dizin taraması Ayrı dizinlenmiş değer kümesini okuyun ve işlem veri deposundan yalnızca eşleşen öğeleri yükleyin Contains, EndsWith, RegexMatch, LIKE Dizine alınan özelliklerin kardinalitesine göre doğrusal olarak artar Sorgu sonuçlarındaki öğe sayısına göre artar
Tam tarama İşlem veri deposundaki tüm öğeleri yükleme Üst, Alt Yok Kapsayıcıdaki öğe sayısına göre artar

Sorgu yazarken, dizini mümkün olduğunca verimli bir şekilde kullanan filtre koşullarını kullanmanız gerekir. Örneğin, kullanım örneğinde işe yarayacağı veya işe yarayacağı durumlarda StartsWith Contains , tam dizin taraması yerine kesin bir dizin taraması yaptığı için StartsWith bunu tercih etmeniz gerekir.

Dizin kullanımı ayrıntıları

Bu bölümde sorguların dizinleri nasıl kullandığı hakkında daha fazla ayrıntı ele alınmaktadır. Azure Cosmos DB'yi kullanmaya başlamayı öğrenmek için bu ayrıntı düzeyi gerekli değildir, ancak meraklı kullanıcılar için ayrıntılı olarak belgelenmiştir. Bu belgenin önceki bölümlerinde paylaşılan örnek öğeye başvuruyoruz:

Örnek öğeler:

{
  "id": 1,
  "locations": [
    { "country": "Germany", "city": "Berlin" },
    { "country": "France", "city": "Paris" }
  ],
  "headquarters": { "country": "Belgium", "employees": 250 },
  "exports": [
    { "city": "Moscow" },
    { "city": "Athens" }
  ]
}
{
  "id": 2,
  "locations": [
    { "country": "Ireland", "city": "Dublin" }
  ],
  "headquarters": { "country": "Belgium", "employees": 200 },
  "exports": [
    { "city": "Moscow" },
    { "city": "Athens" },
    { "city": "London" }
  ]
}

Azure Cosmos DB ters dizin kullanır. Dizin, her JSON yolunu bu değeri içeren öğe kümesine eşleyerek çalışır. Öğe kimliği eşlemesi, kapsayıcı için birçok farklı dizin sayfasında temsil edilir. Aşağıda, iki örnek öğe içeren kapsayıcıya yönelik ters dizine ilişkin örnek bir diyagram verilmişti:

Yol Değer Öğe kimlikleri listesi
/locations/0/country Almanya 1
/locations/0/country İrlanda 2
/locations/0/city Berlin 1
/locations/0/city Dublin 2
/locations/1/country Fransa 1
/locations/1/city Paris 1
/genel merkez/ülke Belçika 1, 2
/headquarters/employees 200 2
/headquarters/employees 250 1

Ters çevrilmiş dizinin iki önemli özniteliği vardır:

  • Belirli bir yol için değerler artan düzende sıralanır. Bu nedenle, sorgu altyapısı dizinden kolayca hizmet ORDER BY verebilir.
  • Belirli bir yol için sorgu altyapısı, sonuçların bulunduğu dizin sayfalarını tanımlamak için farklı olası değerler kümesini tarar.

Sorgu altyapısı, ters çevrilmiş dizini dört farklı şekilde kullanabilir:

Dizin arama

Aşağıdaki sorguyu göz önünde bulundurun:

SELECT location
FROM location IN company.locations
WHERE location.country = 'France'

Sorgu koşulu (herhangi bir konumda ülke/bölge olarak "Fransa" bulunan öğelere göre filtreleme), bu diyagramda vurgulanan yol ile eşleşir:

Ağaç içindeki belirli bir yol ile eşleşen çapraz geçiş (arama) diyagramı.

Bu sorguda eşitlik filtresi olduğundan, bu ağaçtan geçiş yaptıktan sonra sorgu sonuçlarını içeren dizin sayfalarını hızla tanımlayabiliriz. Bu durumda sorgu altyapısı, Öğe 1 içeren dizin sayfalarını okur. Dizin arama, dizini kullanmanın en verimli yoludur. Dizin aramasıyla yalnızca gerekli dizin sayfalarını okur ve sorgu sonuçlarındaki öğeleri yükleriz. Bu nedenle, toplam veri hacminden bağımsız olarak dizin arama süresi ve dizin aramasından gelen RU ücreti inanılmaz derecede düşüktür.

Kesin dizin taraması

Aşağıdaki sorguyu göz önünde bulundurun:

SELECT *
FROM company
WHERE company.headquarters.employees > 200

Sorgu koşulu (200'den fazla çalışanın bulunduğu öğelere göre filtreleme), yolun tam dizin taramasıyla headquarters/employees değerlendirilebilir. Kesin bir dizin taraması yaparken sorgu altyapısı, yolun değerinin 200 konumunu bulmak için headquarters/employees farklı olası değerler kümesini ikili olarak arayarak başlar. Her yolun değerleri artan düzende sıralandığından, sorgu altyapısının ikili arama yapması kolaydır. Sorgu altyapısı değerini 200buldukktan sonra kalan tüm dizin sayfalarını (artan yönde) okumaya başlar.

Sorgu altyapısı gereksiz dizin sayfalarını taramaktan kaçınmak için ikili arama gerçekleştirebildiğinden, kesin dizin taramaları dizin arama işlemleri için benzer gecikme süresine ve RU ücretlerine sahip olma eğilimindedir.

Genişletilmiş dizin taraması

Aşağıdaki sorguyu göz önünde bulundurun:

SELECT *
FROM company
WHERE STARTSWITH(company.headquarters.country, "United", true)

Sorgu koşulu (büyük/küçük harfe duyarlı olmayan "United" ile başlayan bir konumda merkezi olan öğelere göre filtreleme), yolun genişletilmiş dizin taramasıyla headquarters/country değerlendirilebilir. Genişletilmiş dizin taraması yapılan işlemlerin, her dizin sayfasını tarama gereksinimini önlemeye yardımcı olabilecek iyileştirmeleri vardır, ancak kesin bir dizin taramasının ikili aramasından biraz daha pahalıdır.

Örneğin, büyük/küçük harfe duyarsız StartsWithdeğerini değerlendirirken, sorgu altyapısı büyük ve küçük harf değerlerinin farklı olası bileşimleri için dizini denetler. Bu iyileştirme, sorgu altyapısının çoğu dizin sayfasını okumasını önler. Farklı sistem işlevleri, her dizin sayfasını okumaktan kaçınmak için kullanabileceği farklı iyileştirmelere sahiptir, bu nedenle genişletilmiş dizin taraması olarak geniş bir kategoriye ayrılmıştır.

Tam dizin taraması

Aşağıdaki sorguyu göz önünde bulundurun:

SELECT *
FROM company
WHERE CONTAINS(company.headquarters.country, "United")

Sorgu koşulu (merkezi "United" içeren bir konumda olan öğelere filtre uygulama), yolun dizin taramasıyla headquarters/country değerlendirilebilir. Tam dizin taramasının aksine, tam dizin taraması sonuçların bulunduğu dizin sayfalarını tanımlamak için her zaman farklı olası değerler kümesini tarar. Bu durumda, Contains dizinde çalıştırılır. Dizin taramaları için dizin arama süresi ve RU ücreti, yolun kardinalitesi arttıkça artar. Başka bir deyişle, sorgu altyapısının taraması gereken olası benzersiz değerler ne kadar yüksek olursa, tam dizin taraması yaparken gecikme süresi ve RU ücreti o kadar yüksek olur.

Örneğin, iki özelliği göz önünde bulundurun: town ve country. Şehrin kardinalitesi 5.000 ve kardinalitesi country 200'dür. Aşağıda, her birinin özelliğinde tam dizin taraması yapabilen bir Contains system işlevine sahip olan iki örnek sorgu verilmiştir town . şehir kardinalitesi değerinden yüksek olduğundan ilk sorgu ikinci sorgudan countrydaha fazla RU kullanır.

SELECT *
FROM c
WHERE CONTAINS(c.town, "Red", false)
SELECT *
FROM c
WHERE CONTAINS(c.country, "States", false)

Tam tarama

Bazı durumlarda, sorgu altyapısı dizini kullanarak bir sorgu filtresini değerlendiremeyebilir. Bu durumda sorgu filtresinin değerlendirilmesi için sorgu altyapısının işlem deposundaki tüm öğeleri yüklemesi gerekir. Tam taramalar dizini kullanmaz ve toplam veri boyutuyla doğrusal olarak artan bir RU ücretine sahiptir. Neyse ki, tam tarama gerektiren işlemler nadirdir.

Tanımlı vektör dizini olmayan vektör arama sorguları

Vektör dizin ilkesi tanımlamazsanız ve sistem işlevini bir ORDER BY yan tümcede kullanırsanızVectorDistance, bu tam taramaya neden olur ve bir vektör dizin ilkesi tanımladığınızdan daha yüksek bir RU ücretine sahip olur. Benzerlik, deneme yanılma boole değeri olarak ayarlanmış truevectorDistance kullanıyorsanız ve vektör yolu için tanımlanmış bir flat dizininiz yoksa, tam tarama gerçekleşir.

Karmaşık filtre ifadelerine sahip sorgular

Önceki örneklerde yalnızca basit filtre ifadelerine sahip sorguları (örneğin, tek bir eşitliğe veya aralık filtresine sahip sorgular) ele almıştık. Gerçekte çoğu sorguda çok daha karmaşık filtre ifadeleri vardır.

Aşağıdaki sorguyu göz önünde bulundurun:

SELECT *
FROM company
WHERE company.headquarters.employees = 200 AND CONTAINS(company.headquarters.country, "United")

Bu sorguyu yürütmek için sorgu altyapısı üzerinde bir dizin araması headquarters/employees ve üzerinde headquarters/countrytam dizin taraması yapmalıdır. Sorgu altyapısı, sorgu filtresi ifadesini mümkün olduğunca verimli bir şekilde değerlendirmek için kullandığı iç buluşsal yöntemlere sahiptir. Bu durumda sorgu altyapısı, önce dizin aramasını yaparak gereksiz dizin sayfalarını okuma gereksinimini ortadan kaldıracak. Örneğin, eşitlik filtresiyle yalnızca 50 öğe eşleşmişse, sorgu altyapısının yalnızca bu 50 öğeyi içeren dizin sayfalarında değerlendirmesi Contains gerekir. Kapsayıcının tamamının tam dizin taraması gerekmez.

Skaler toplama işlevleri için dizin kullanımı

Toplama işlevlerine sahip sorguların kullanabilmesi için yalnızca dizine güvenmesi gerekir.

Bazı durumlarda dizin hatalı pozitifler döndürebilir. Örneğin, dizinde değerlendirme Contains yaparken, dizindeki eşleşme sayısı sorgu sonuçlarının sayısını aşabilir. Sorgu altyapısı tüm dizin eşleşmelerini yükler, yüklenen öğelerdeki filtreyi değerlendirir ve yalnızca doğru sonuçları döndürür.

Çoğu sorguda hatalı pozitif dizin eşleşmelerinin yüklenmesi dizin kullanımı üzerinde belirgin bir etkiye sahip değildir.

Örneğin, aşağıdaki sorguyu göz önüne alın:

SELECT *
FROM company
WHERE CONTAINS(company.headquarters.country, "United")

Contains Sistem işlevi bazı hatalı pozitif eşleşmeler döndürebilir, bu nedenle sorgu altyapısının yüklenen her öğenin filtre ifadesiyle eşleşip eşleşmediğini doğrulaması gerekir. Bu örnekte sorgu altyapısının yalnızca fazladan birkaç öğe yüklemesi gerekebilir, bu nedenle dizin kullanımı ve RU ücreti üzerindeki etkisi çok azdır.

Ancak, toplama işlevlerine sahip sorguların kullanabilmesi için yalnızca dizine güvenmesi gerekir. Örneğin, toplama ile Count aşağıdaki sorguyu göz önünde bulundurun:

SELECT COUNT(1)
FROM company
WHERE CONTAINS(company.headquarters.country, "United")

İlk örnekte olduğu gibi, Contains sistem işlevi bazı hatalı pozitif eşleşmeler döndürebilir. Ancak sorgudan SELECT * farklı olarak sorgu, Count tüm dizin eşleşmelerini doğrulamak için yüklenen öğelerdeki filtre ifadesini değerlendiremez. Sorgu yalnızca Count dizine bağlı olmalıdır, bu nedenle bir filtre ifadesinin hatalı pozitif eşleşmeler döndürme olasılığı varsa, sorgu altyapısı tam taramaya başvurur.

Aşağıdaki toplama işlevlerine sahip sorguların yalnızca dizine bağlı olması gerekir, bu nedenle bazı sistem işlevlerinin değerlendirilmesi tam tarama gerektirir.

Sonraki adımlar

Dizin oluşturma hakkında daha fazla bilgiyi aşağıdaki makalelerde bulabilirsiniz: