MySQL'de iki tek sütunlu dizin mi yoksa iki sütunlu dizin mi?


114

Aşağıdakilerle karşı karşıyayım ve en iyi uygulamanın ne olduğundan emin değilim.

Aşağıdaki tabloyu düşünün (genişleyecek):

id PK | giver_id FK | alıcı_kimliği FK | tarih

InnoDB kullanıyorum ve anladığım kadarıyla, iki yabancı anahtar sütunu için otomatik olarak endeksler oluşturuyor. Bununla birlikte, belirli bir kombinasyonu eşleştirmem gereken çok sayıda sorgu da yapacağım:

SELECT...WHERE giver_id = x AND recipient_id = t.

Bu tür kombinasyonların her biri tabloda benzersiz olacaktır.

Bu sütunların üzerine iki sütunlu bir dizin eklemenin herhangi bir faydası var mı, yoksa teoride iki ayrı dizin yeterli mi / aynı mı?


1
İki sütunun kombinasyonu benzersizse, yalnızca sorgunuzun hızını artırmakla kalmayacak, aynı zamanda tablonuza tutarlılık da katacak benzersiz özelliğe sahip iki sütunlu bir dizin oluşturabilirsiniz.
sguven

"MySQL, dizindeki tüm sütunları test eden sorgular için veya yalnızca ilk sütunu, ilk iki sütunu, ilk üç sütunu vb. Test eden sorgular için çok sütunlu dizinler kullanabilir. Sağdaki sütunları belirtirseniz dizin tanımında, tek bir bileşik dizin, aynı tablodaki çeşitli sorgu türlerini hızlandırabilir. " - Çok Sütunlu Dizinler
AlikElzin-kilaka

@ User1585784 üzerinde tahmin yapmak için; İki sütunun kombinasyonu benzersizse, bence onlar için benzersiz bir anahtar kullanılmalıdır. Aslında, biri veritabanı düzeyinde benzersizliği zorlamak istiyorsa, benzersiz bir anahtar gitmenin en kolay yoludur ...
Erk

Yanıtlar:


133

İki tek sütun dizininiz varsa, örneğinizde bunlardan yalnızca biri kullanılacaktır.

İki sütunlu bir dizininiz varsa, sorgu daha hızlı olabilir (ölçmelisiniz). İki sütunlu bir dizin de tek sütun dizini olarak kullanılabilir, ancak yalnızca ilk listelenen sütun için kullanılabilir.

Bazen (A, B) üzerinde bir indeks ve (B) üzerinde başka bir indeks olması yararlı olabilir. Bu, sütunlardan birini veya her ikisini kullanarak sorguları hızlı hale getirir, ancak elbette daha fazla disk alanı da kullanır.

Dizinleri seçerken, ekleme, silme ve güncelleme üzerindeki etkisini de göz önünde bulundurmanız gerekir. Daha fazla dizin = daha yavaş güncellemeler.


1
"MySQL, dizindeki tüm sütunları test eden sorgular için veya yalnızca ilk sütunu, ilk iki sütunu, ilk üç sütunu vb. Test eden sorgular için çok sütunlu dizinler kullanabilir. Sağdaki sütunları belirtirseniz dizin tanımında, tek bir bileşik dizin, aynı tablodaki çeşitli sorgu türlerini hızlandırabilir. " - Çok Sütunlu Dizinler
AlikElzin-kilaka

33

Aşağıdakilere benzer bir kaplama indeksi:

ALTER TABLE your_table ADD INDEX (giver_id, recipient_id);

... Bir sorgu sevk eğer endeks kullanılabileceği anlamına gelecektir giver_idveya bir kombinasyonudur giver_idve recipient_id. İndeks ölçütlerinin en sola dayalı olduğuna dikkat edin - yalnızca atıfta bulunan bir sorgu recipient_idsağladığım ifadede kaplama indeksini kullanamaz.

Ek olarak, MySQL, SELECT başına yalnızca bir dizin kullanabilir, bu nedenle bir örtme indeksi, sorgularınızı optimize etmenin en iyi yolu olur.


10
MySQL can only use one index per SELECTbu artık doğru değil, cevabınızı güncellenecek şekilde düzenlerseniz iyi olur.
Davor

Örtme indeksinin neden kullanılamayacağını açıklar recipient_idmısınız?
Ivo Pereira

2
MySQL'deki @IvoPereira Multi sütun dizinleri, dizindeki tüm alanları soldan sağa kullanmanıza izin verir. Örneğin, bir varsa, INDEX (col1, col2, col3, col4)o zaman dizin, veya veya WHEREgibi bir cümleye sahip aramalar için uygulanacaktır , ancak bu belirli dizin, benzeri herhangi bir şey için veya arama alanlarının dizin tanımında en fazla bırakılmaması nedeniyle kullanılmayacaktır . Bu alanları kapsayacak ek dizinler eklemeniz gerekir. col1 = 'A'col1 = 'A' AND col2 = 'B'col1 = 'A' AND col2 ='B' AND col3 = 'C' AND col4 = 'D'WHERE col2 = 'B'WHERE col3 = 'C' AND col4 = 'D'
Slicktrick

"SEÇİM başına bir dizin" , bu hala mariadb 10.1 için geçerli mi?
oldboy

1
@Anthony: Hayır. Davor'un yukarıdaki yorumuna bakın.
kapad

4

Yabancı anahtar dizinlerinden biri zaten çok seçiciyse, veritabanı motoru belirttiğiniz sorgu için bunu kullanmalıdır. Çoğu veritabanı motoru, bu durumda en uygun dizini seçebilmek için bir tür sezgisel kullanır. Her iki dizin de kendi başına çok seçici değilse, bu tür bir sorguyu çok kullanacağınızı söylediğiniz için her iki anahtar üzerine kurulu dizini eklemek muhtemelen mantıklı olacaktır.

Dikkate alınması gereken bir diğer husus, bu tablodaki PK alanını ortadan kaldırıp giver_idve recipient_idalanları üzerindeki birincil anahtar dizinini tanımlayıp tanımlayamayacağınızdır . Kombinasyonun benzersiz olduğunu söylediniz, bu yüzden muhtemelen işe yarayabilir (yalnızca sizin cevaplayabileceğiniz birçok başka koşul göz önüne alındığında). Yine de, tipik olarak, eklenen karmaşıklığın uğraşmaya değmediğini düşünüyorum.


Teşekkürler Mark, anahtarlardan biri gerçekten çok seçici, bu yüzden iyi olmalı. İki (otomatik) endeksi yerinde tutmayı ve zaman içinde nasıl performans gösterdiğini görmeyi seçtim. Ayrıca birleşik bir verici: alıcı birincil anahtarı hakkında düşündüm, ancak her alanın ayrı ayrı aranması gerektiğinden, sadece php ek yükü eklerdi. Ayrıca, yeni anahtar (daha kısa) bir tam sayı yerine (daha uzun) bir dizge olacaktır.
Tom

2

Dikkate alınması gereken bir diğer husus da, her iki yaklaşımın performans özelliklerinin veri setinin boyutuna ve önemine dayalı olmasıdır. 2 sütunlu dizinin yalnızca belirli bir veri kümesi boyutu eşiğinde veya tam tersinde daha performanslı olduğunu fark edebilirsiniz. Kesin senaryonuz için hiçbir şey performans ölçütlerinin yerini alamaz.


lütfen bununla ilgili bazı belgelere bağlantı verebilir misiniz? Teşekkürler.
kapad
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.