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:
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 BY
filtreli sorgular. Filtre özelliği yan tümcesineORDER 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:
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 200
buldukktan 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 StartsWith
değ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 country
daha 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ış true
vectorDistance 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/country
tam 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: