2012-11-18 14 views
8

Sık sık katılımcılar için bir alan kullanacağınızı biliyorsanız, bunun üzerinde bir dizin oluşturmanın iyi olabileceği söylendi.SQL tablo alanına (MySQL) bir dizin eklemek ne zaman?

Genellikle (kağıt kitapta bir dizin Eğer sayfa sayfa aramak zorunda kalmadan belirli bir terim bakmak için izin verir çok gibi) bir tablo indeksleme kavramını anlamak. Ama onları ne zaman kullanacağım konusunda daha net değilim. Bir KULLANICI, YORUMLAR ve VOTES tablo:

Diyelim

3 tablolar var. Ve sorguların yorumların yanı sıra bu yorumlarda yukarı/aşağı oyların sayılarını döndürdüğü Stackoverflow benzeri yorumlama iş parçacığı yapmak istiyorum.
USERS table 
user_id user_name 
1   tim 
2   sue 
3   bill 
4   karen 
5   ed 

COMMENTS table 
comment_id topic_id comment commenter_id 
1   1  good job!   1 
2   2  nice work   2 
3   1  bad job :)  3 

VOTES table 
vote_id vote comment_id voter_id 
    1   -1  1   5 
    2   1  1   4 
    3   1  3   1 
    4   -1  2   5 
    5   1  2   4 

Here's the query and SQLFiddle to return the votes on topic_id=1

:
select u.user_id, u.user_name, 
    c.comment_id, c.topic_id, c.comment, 
    count(v.vote) as totals, sum(v.vote > 0) as yes, sum(v.vote < 0) as no, 
    my_votes.vote as did_i_vote 
from comments c 
join users u on u.user_id = c.commenter_id 
left join votes v on v.comment_id = c.comment_id 
left join votes my_votes on my_votes.comment_id = c.comment_id 
and my_votes.voter_id = 1 
where c.topic_id = 1 
group by c.comment_id, u.user_name, c.comment_id, c.topic_id, did_i_vote; 

yorumlarına ve oy sayısı milyonlara gider varsayalım. Sorguyu hızlandırmak için sorum, comments.commenter_id, votes.voter_id ve votes.comment_id dizinlerine bir dizin koymalı mıyım?

+1

Sorguları hızlandırdıklarında kullanın. –

+0

@SteveWellens, uygun indeksleri bir cevapta ve/veya [SQLFiddle] (http://www.sqlfiddle.com/#!2/b562a/13) eklemek için SQL kodunu sağlayabilir misiniz? –

+1

Ayrıca, 'topic_id' dizinine bir dizin eklemeniz gerekir. – Skpd

cevap

3

İşte http://www.sqlfiddle.com/#!2/94daa/1

motor Bunu yaparken değil maliyeti ile bir dizin kullanmanın maliyeti karşılaştırmak zorundadır alışması bazı anahtarlar ile bir güncelleme var. Kullanılan dizinleri almak için daha fazla satır eklemem gerektiğine dikkat edersiniz. endeksi ile

, motor hızlı olan eşleşen değerleri elde etmek endeksi kullanmak zorundadır. Sonra, tablodaki gerçek satırları aramak için kibritleri kullanmak zorundadır. Dizin satır sayısını daraltmazsa, yalnızca tablodaki tüm satırları aramak daha hızlı olabilir.

Eğer mysql SQL Server kümelenmiş dizinlerine benzer bir şey varsa emin değilim. Bu durumda, dizin ve tablo verileri aynı yapıdadır, bu nedenle dizin aramanın ikinci adımına sahip değilsiniz.

Ben bir birincil anahtar tanımlayarak öncelikle kullanıcıların masaya, iki farklı şekilde dizinleri tanıtıldı. Bu, dolaylı olarak user_id sütununda benzersiz bir dizin oluşturacaktır. Eşsiz bir indeks, aynı değerler kümesini iki kez ekleyemezseniz anlamına gelir. Tek bir sütun dizini için bu sadece iki kez aynı değere sahip olamayacağınız anlamına gelir. sayfa başına bir kullanıcı ile tablo için kullanıcıların bir kitap, hayal ise

ardından oluşturulan endeks kullanıcının sayfa numarası ile her size user_id sıralı bir liste verir. Liste genellikle belirli bir numaraya hızlı bir şekilde bakmak için bir tür ağaç formunda saklanır. Bir telefon rehberindeki bir isme bakma şeklini düşünün, sadece siz onu bulana kadar tüm sayfaları taratmayın, nerede olacağını tahmin edin ve daha sonra kapanana kadar sayfaların parçalarını ileri veya geri alın . Normalde O (dizin n) zamanındaki bir dizindeki değerleri arayabilir, burada n satır sayısıdır ve benzer sayıda dizin sayfası okumalısınız. DB motoru sorgusu select * from users Where user_id = 3 verilirse

Şimdi, iki seçenek vardır. Her bir veri sayfasını okuyabilir ve doğru değeri arar (ilk önce durdurmak için birincil bir anahtar olduğu gerçeğini kullanabilir). Alternatif, doğru veri sayfasını almak için indeksi okumak ve ardından veri sayfasına bakmaktır.

Somutluk ve basitlik için, tablonun 1024 girişi olduğunu varsayalım. Her girişin bir veri sayfası aldığını varsayalım. Dizin ağacındaki her girdinin bir dizin sayfası aldığını varsayalım. Endeksin dengeli olduğunu varsayın, bu yüzden 10 seviyeye ve toplam 2047 sayfaya sahip.(tüm bu varsayımlar şüphelidir, ancak noktaları birbiriyle karıştırırlar, özellikle tüm sütunları aynı anda endeksleme eğiliminde olmadıkça özellikle dizin sayfaları neredeyse her zaman veri sayfalarından daha küçüktür).

Tablo taraması yapmak için yaklaşım 1024 veri sayfasını okumalıdır. İndeksi kullanmak için 10 dizin sayfasını ve bir veri sayfasını okuması gerekir. Hemen hemen tüm veritabanı performansı, okunan sayfaların sayısını en aza indirmektir.

Çoklu sütun dizinleri, hızlı bir şekilde veri kümelerine bakmayı sağlar. Eğer (col1, col2) ile bir endeksiniz varsa, sadece col1 ile eşleşir.

create index ifadesi, yalnızca hangi sütunların dizine eklendiğini ve yinelenen değerlerin izin verilip verilmeyeceğini belirtir.

Kitap benzetimini tekrar kullanarak, Create Index ix_comment_id on votes (comment_id, voter_id), sıralı bir veri satırı referansı ile bir sıradaki comment_id ve ardından seçmen_id listesini yaratacaktır.

+------------+--------------+---------+ 
| comment_id | reference_id | row_ref | 
+------------+--------------+---------+ 
|   1 |   4 | ref1 | 
|   1 |   5 | ref2 | 
|   2 |   4 | ref3 | 
|   2 |   5 | ref4 | 
|   3 |   1 | ref5 | 
+------------+--------------+---------+ 
+0

- @ Laurence, adım atmak zorundayım 2 saat boyunca dışarı çıktım ama bundan sonra kodunuzu kontrol edip üzerine yorum yapacağım, cevabınız için teşekkürler! –

+0

Cevabınızı kabul etmek istiyorum, ancak eksiksizlik için, ilk önce cevabınıza kodun 'CREATE INDEX 'kısmı için bir açıklama ekleyebilir misiniz? –

+1

@timpeterson Biraz daha açıklama eklendi. – Laurence

15

SQL tablolarında dizinlerin nerede kullanılacağı her zaman net bir kesim değildir. Ancak, çoğu durumda karar vermenize yardımcı olabilecek bazı genel genel kurallar vardır. Üzerinde katılmak için kullanmak sütunlar üzerinde nerede cümleleri

  • koyun endeksinde kullanılmakta olan sütunlar üzerinde

    1. koyun indeksi.
    2. Aynı tablodaki sütunlarda 4-5'ten fazla dizin kullanmayın.

    Ve akılda tutulması gereken genel kavramlar şunlardır:

    1. daha hızlı bu sütunların üzerine aramalar yapacak kullanmak Herhangi dizini.
    2. Eklediğiniz herhangi bir dizin, bu tabloya eklenmeye neden olmanın biraz daha yavaş olmasını sağlar.
    3. Önceki ikisinden. İndeks kullanılıp kullanılmayacağına ve hangi sütunlarda kullanılıp kullanılmayacağına karar vermek için tablolarda kaç ekleme ve sorgulama yaptığınıza karar vermek sizin sorumluluğunuzdadır.

    DÜZENLEME

    @AndrewLazarus açıklama gerçekten önemlidir ve ben cevap eklemek için karar:

    1. sadece birkaç farklı değerlere sahip sütunlarda dizinleri kullanmayın. Örneğin, yalnızca birkaç durum olduğunda veya bir boole değeri olduğunda bir durumu tutan bir sütun. Bunu yapmamanın nedeni, endeksin gerçekten size yardım etmemesidir, çünkü sadece değerlerin sayısına bölünecektir ve sadece birkaç taneniz olduğundan, gerçek bir fayda olmayacaktır. Tablo, endeksle daha fazla alan ve preformda preformu daha yavaş tüketir, ancak
  • +0

    - @ goBeepit dev, teşekkürler, olabilir/SQLFiddle kullanıyorum kod oluştururken indeks eklemek için bazı kod cevap eklemek? –

    +1

    Ayrıca, yalnızca birkaç ayrı değer alan sütunlarda dizinlerle uğraşmayın. –

    +0

    @AndrewLazarus, bu demektir ki "oylama" sütununa bir değer koyma (value = -1 veya 1), ancak bir "xxx_id" sütununa (burada değer = 1-> sonsuz) koyulsun mu? –

    İlgili konular