SQL INDEX - nasıl çalışır?


19

Veritabanları ve SQL hakkındaki bilgim çoğu üniversite dersine dayanmaktadır. Her neyse, veritabanlarıyla çalıştığım bir şirkette birkaç ay (neredeyse bir yıl) geçirdim.

Ben birkaç kitap okudum ve o şekilde veritabanları hakkında birkaç eğitimlere katılmış MySQL, PostgreSQL, SQLite, Oracleve ayrıca birkaç nonSQL dbbizi ler böyle MongoDB, Redis, ElasticSearchvb

Dediğim gibi, ben çok fazla bilgi eksikliği ile acemi değilim, ama bugün, birisi bir şey söyledi, tamamen benim acemi bilgisine karşı olan şey.

Açıklamama izin ver. SQL veritabanını alalım ve Personiçinde birkaç kayıt içeren basit bir tablo oluşturalım :

id | name   | age
-----------------
1  | Alex   | 24
2  | Brad   | 34
3  | Chris  | 29
4  | David  | 28
5  | Eric   | 18
6  | Fred   | 42
7  | Greg   | 65
8  | Hubert | 53
9  | Irvin  | 17
10 | John   | 19
11 | Karl   | 23

Şimdi, odaklanmak istediğim kısım idbu INDEX.

Şimdiye kadar, bu şekilde çalıştığını düşündüm: bir tablo oluşturulduğunda INDEXboş. INDEXMasama yeni kayıt eklerken bazı alghortims dayalı yeniden hesaplanıyor. Örneğin:

Tek tek gruplama:

1    ... N
N+1  ... 2N
     ...
XN+1 ... (X+1)N

yani, benim örnek ile size = 11 elementsve N = 3böyle olacak:

id | name   | age
-----------------
1  | Alex   | 24     // group0
2  | Brad   | 34     // group0
3  | Chris  | 29     // group0
4  | David  | 28     // group1
5  | Eric   | 18     // group1
6  | Fred   | 42     // group1
7  | Greg   | 65     // group2
8  | Hubert | 53     // group2
9  | Irvin  | 17     // group2
10 | John   | 19     // group3
11 | Karl   | 23     // group3

Yani, ben sorgu kullanırken SELECT * FROM Person WHERE id = 8bazı basit hesaplama yapacağız 8 / 3 = 2, bu yüzden bu nesneyi aramak zorunda group2ve sonra bu satır döndürülür:

8  | Hubert | 53

resim açıklamasını buraya girin

Bu yaklaşım zamanlı olarak çalışır O(k)nerede k << size. Tabii ki, gruplar halinde satırları düzenlemek için bir alghoritm çok daha karmaşıktır, ancak bence bu basit örnek bakış açımı gösteriyor.

Şimdi, bugün bana gösterilen başka bir yaklaşım sunmak istiyorum.

Bu tabloyu bir kez daha alalım:

id | name   | age
-----------------
1  | Alex   | 24
2  | Brad   | 34
3  | Chris  | 29
4  | David  | 28
5  | Eric   | 18
6  | Fred   | 42
7  | Greg   | 65
8  | Hubert | 53
9  | Irvin  | 17
10 | John   | 19
11 | Karl   | 23

Şimdi, benzer bir şey yaratıyor Hashmapharitalar (aslında, tam anlamıyla bir Hash Haritası) idiçin addressbu kimliği ile satırın. Diyelimki:

id | addr 
---------
1  | @0001
2  | @0010
3  | @0011
4  | @0100
5  | @0101
6  | @0110
7  | @0111
8  | @1000
9  | @1001
10 | @1010
11 | @1011

Şimdi sorgumu çalıştırırken: SELECT * FROM Person WHERE id = 8

doğrudan id = 8bellekteki adrese eşlenir ve satır döndürülür. Elbette bunun karmaşıklığı O(1).

Şimdi birkaç sorum var.

1. Her iki çözümün de avantajları ve dezavantajları nelerdir?

2. Mevcut veritabanı uygulamalarında hangisi daha popüler? Belki farklı dbs farklı yaklaşımlar kullanır?

3. NonSQL dbs içinde var mı?

Şimdiden teşekkür ederim


KARŞILAŞTIRMA

               |      B-tree     |   Hash Table
----------------------------------------------------
----------------   one element   -------------------
----------------------------------------------------
SEARCHING      |  O(log(N))      | O(1) -> O(N)  
DELETING       |  O(log(N))      | O(1) -> O(N)
INSERTING      |  O(log(N))      | O(1) -> O(N)
SPACE          |  O(N)           | O(N)
----------------------------------------------------
----------------    k elements   -------------------
----------------------------------------------------
SEARCHING      |  k + O(log(N))  | k * O(1) -> k * O(N)
DELETING       |  k + O(log(N))  | k * O(1) -> k * O(N)
INSERTING      |  k + O(log(N))  | k * O(1) -> k * O(N)
SPACE          |  O(N)           | O(N)

N - kayıt sayısı

Haklı mıyım? Her ekleme / silme işleminden sonra B-ağacı ve Karma tablosunu yeniden oluşturma maliyeti nedir ? B-ağacı durumunda, bazı işaretçileri değiştirmemiz gerekir, ancak dengeli b-ağacı durumunda daha fazla çaba gerektirir. Ayrıca Hash tablosunda , özellikle operasyonumuz çakışmalar yaratıyorsa, çok az işlem yapmalıyız .


2
İkinci olarak, bir karma indeksi tanımlıyorsunuz. O(1)Seninle ilgili kısım doğru anladı! İlk olarak, bir B-ağacı endeksini tanımladığınız anlaşılıyor, ancak bazı yanlış anlamalarınız var. Hesaplama yoktur (3'e veya herhangi bir şeye bölünme), ağacın daha fazla seviyesi olduğu için daha karmaşıktır (bir ağaçtır, büyük, küçük, daha küçük dalları vardır ... ve sonra ayrılır :)
ypercubeᵀᴹ

3
BTrees: en.m.wikipedia.org/wiki/B-tree , üniversitenizde bunu açıklayan bir algoritma kursu olmadığına şaşırdı
Philᵀᴹ

@ypercube Merhaba, Cevabınız için teşekkür ederim. Yazdığım gibi: Of course, an alghoritm to organise rows in groups is for sure much more complicated but I think this simple example shows my point of view.Tabii ki, bunun çok daha karmaşık olduğunu biliyorum. Son olarak, kodumda INDEXhangi çözümlerimin ( 1. veya 2. ) bu gerçek olana daha yakın olduğunu söylerken ? Ve bir kayda göre erişmek için gereken süre ne olacak INDEX. Gerçekten O(1)mi? B-ağacı endeksi ile çok benzer O(log2(N)). Haklı mıyım?
ruhungry

@FreshPhilOfSO Sanırım (daha da fazlası, eminim) bu konuda bazı dersler oldu. Muhtemelen, bir şey kaçırdım ...
ruhungry

ElasticSearch B ağaçları tamamen farklı ters dizinleri kullanır elastic.co/blog/found-elasticsearch-from-the-bottom-up
Lluis Martinez

Yanıtlar:


12

Temel olarak bir B-ağacı indeksi ve bir karma indeksini tarif ediyorsunuz. Her ikisinin de bir yeri var, ancak her ikisi de farklı işler için en uygun.

Avantajlar ve dezavantajlar

B-ağacı (ve B +-ağacı) indeksleri genellikle dengelenir. Bu, bir değer aramanın, ağacın neresinde olursa olsun her zaman aynı süreyi alacağı anlamına gelir (O ​​(log n)). Genel olarak, ağaçtaki seviyelerin sayısı sınırlıdır, bu nedenle "daha derin" değil "daha geniş" olma eğilimindedir. Bununla birlikte, küçük veri kümeleri için B-ağacının bakım ve kullanım maliyeti tüm satırları okumaktan daha fazla olabilir. B-ağacı dizinleri, büyük veri kümeleri, düşük seçiciliğe sahip veri kümeleri veya yalnızca bir nesne değil, bir dizi nesne seçmek istediğiniz veri kümeleri için iyidir.

Karma tablolar küçük veri kümeleri için mükemmeldir. Karma dizinler, kullanılan karma algoritmaya bağlı olarak önceden tanımlanmış sayıda karma kovaya sahiptir. Bunun nedeni, belirli bir karma algoritmanın yalnızca çok fazla benzersiz karma üretebilmesidir, bu nedenle yalnızca "daha geniş" değil "daha derin" olur. Veritabanı motoru doğru kovayı bulduktan sonra, istediğiniz kovayı bulmak için o kovadaki tüm nesneleri dolaşır. Küçük, son derece seçici veri kümeleriyle, her grup çok az sayıda nesne içerir ve oldukça hızlı bir şekilde çözülür. Daha büyük veri kümeleriyle, kovalar çok daha fazla kalabalıklaşır. Yani, ihtiyacınız olan nesne küçük bir kovadaysa veya kova başlangıcına yakınsa, oldukça hızlı bir şekilde geri döner. Büyük bir kovanın sonundaysa, daha uzun sürer. Dizin dengelenmediği için performans O (1) ila O (n) arasındadır.

Popülerlik

Genel olarak en çok B-ağaçlarıyla karşılaştım. Bitmap dizinleri de düşük kardinaliteye sahip değerler için başka bir seçenektir (bence booleans veya belki cinsiyet). Bu, hangi dizin türlerinin kullanılabilir olduğuna bağlı olarak veritabanı motorunuza bağlı olarak değişecektir.

NoSQL

NoSQL veritabanları kesinlikle dizinleri destekler. Çoğu B-ağacını veya B-ağacındaki bir varyasyonu destekler. Çoğu, karma dizinleri de destekliyor gibi görünüyor.


4
B + ağaçlarındaki seviye sayısının sabit olduğunu düşünmüyorum. En azından bildiğim kadarıyla SQL Server'da değil.
ypercubeᵀᴹ

1
Bu doğru. Bir B ağacının herhangi bir sayıda seviyesi olabilir, ancak genellikle 3 veya 4 ile sınırlıdır. Cevabımı düzenledim.
sarme

Merhaba @sarme. Cevabınızı gerçekten beğendim. Çok açıklıyor. Bu soru için ödül almaya başlamamın bir sakıncası yok mu? Belki birisi ilginç bir şey ekler.
ruhungry

1
Bitmap indeksi için düşük kardinalite demek istemiyor musunuz?
Mihai

1
Doğru, DÜŞÜK kardinalite. Soruları yatmadan hemen önce cevaplamayı bırakmalıyım :). Yanıt güncellendi.
sarme

4

Her iki çözümün de avantajları ve dezavantajları nelerdir? İkinci çözüm aralık taraması yapamaz. Tek bir kimlik seçmek harika. Peki ya 3'ten 8'e kadar kimlikler istiyorsanız? Gerçek dünyada almak için sadece O (1) * 6 kayıtları değil tüm kayıtları bireysel kapmak zorunda. HashMap dizinine sahip büyük bir üretim veritabanında, diske vurmanızı ve altı farklı sayfayı belleğe okumanızı gerektiren farklı sayfalarda kayıtlar alırsınız.

Bir B-Tree yapısında, ilk durumunuzun gerçekte nasıl uygulanacağı gibi, id'ler disk üzerinde sıralı olacak ve tek bir sayfa muhtemelen ids 3 - 8 tutacak ve bireysel tarama O hızını artıracaktır (log n) .

Mevcut veritabanı uygulamalarında hangisi daha popüler? Belki farklı dbs farklı yaklaşımlar kullanır? Birçok farklı veritabanında çok büyük bir deneyimim yok. Sql Server'ın çoğunlukla B-Ağaçları kullandığını biliyorum, ancak SQl 2014'ün bazı tablolarda kullanabileceğiniz bazı yeni Hash Indexleri var. No Sql veritabanlarının ve önbellek veritabanlarının bir çok duyduğumda, tek tek kayıtları alıp karma dizinleri kullanıyorum. Bu, önbellekler için anlamlıdır, çünkü A kullanıcısı için kayıt istersiniz ve aralık taramaları gerekmez.

SQL dışı dbs var mı? Evet. Postgressql için dizin oluşturma belgeleri hızlı bir göz alarak Ben hem Hash hem de B-Tree dizinleri yanı sıra birkaç diğerleri destekler görüyorum.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.