2009-05-27 21 views
10

SQL'de iyi değilim. Ben binlerce kez bu onlarca yapıyorumNasıl Hızlandırılır Simple Join

SELECT 
    E.expressionID, 
    A.attributeName, 
    A.attributeValue 
FROM 
    attributes A 
JOIN 
    expressions E 
ON 
    E.attributeId = A.attributeId 

ve masa büyüdükçe daha fazla alıyor:

Böyle katılmak bir basit hızlandırmak için bir yol arıyorum.

Dizinleri düşünürüm - Tekli tablolarda hızlandırmayı seçersem, büyük olasılıkla ifadeler tablosu için ifadesi olmayanlar ve öznitelik tablosu için başka bir (attributeName, attributeValue) kümesini küme dışı bırakabilirim. Bunun katılım için nasıl geçerli olabileceğini bil.

DÜZENLEME: Zaten ben ettik

nitelikleri masaya Attributeıd (PK) hakkında ifadeler masaya expressionId (PK), Attributeıd (PK, FK) kümelenmiş bir dizin ve başka kümelenmiş bir dizin var this sorusu görüldü ama daha genel ve muhtemelen çok daha basit bir şey istiyorum.

Herhangi bir yardım için teşekkür ederiz!

+0

Bu sorguda WHERE yan tümcesi var mı? Kaç satır iade ediliyor? – JerSchneid

+0

no WHERE - Bunu kullanarak, eşleşen expressionId – JohnIdol

+1

sorgusunun ikinci yarısını yayınlamanız için bir dizi ad-değer çiftine bağlı olarak bir çok yan tümce ile filtrelenen bir geçici tabloyu doldurmak için kullanıyorum. Bahse girerim ki, yavaşlama, bu geçici masaya çok sayıda kayıt eklemekten kaynaklanır. Muhtemelen WHERE cümleleri büyük eklemeyi önlemek için daha önce kullanıldığından, bunları birleştirerek büyük ölçüde geliştirilebilir. – JerSchneid

cevap

16

attributeID numaralı dizinde hem attributes hem de expressions tablosunda dizinler olmasını kesinlikle istiyorsunuz. Şu anda bu dizinlere sahip değilseniz, büyük bir hızlanma göreceksiniz. iade edilen kadar az sütun olduğundan Aslında

+5

Unutmayalım Her iki sütunun da aynı veri tipinde olması ve aynı harmanlamada karakter verisi olması gerekir. – Tomalak

+1

Birincil anahtarı bilmek yardımcı olacaktır. Birincil anahtar olan tek bir sütun zaten dizine eklenecekti. İfadeler tablonuzun birincil anahtarı oluşturan iki alanı olması mümkündür. Bu, E.attributeId üzerinde bir dizin oluşturmanın yolu olacak demektir. Birincil anahtar, hem E.ID hem de E.attributeId kullanarak bir dizin oluşturacaktır. Yalnızca E.attributeId için bir dizin eklemek hızlandırabilir. – Kieveli

+1

Aslında, birincil anahtar tüm platformlarda otomatik olarak kayıtsız değil. Örneğin MySql, birincil anahtarda varsayılan olarak bir dizin oluşturmaz. –

6

, ben yani sorguda tüm alanlarını kapsayan bir endeks bu sorgu

için kapalı bir indeks ele alacak.

+0

numaralı sorunun DÜZENLENMESİ bir katılımı nasıl dizine ekleyebilirim? (hiç bitmedi) – JohnIdol

+2

Ben Goblyn A.attributeId, A.attributeName, A.attributeValue ve E.attributeId ve E.expressionID üzerinde bir dizin ekleyerek önerdiğini düşünüyorum ... ama% 100 emin değilim. Bu teori, sorgu için tüm verilerin doğrudan endekslerden gelmesi ve asla masaya çarpmamasıdır. – Greg

+0

Özür dilerim, açık değildi. Greg haklı. Bu örnekte, her bir tablo için bir tane olmak üzere iki kapalı dizin olacaktır ve birleştirme, gerçek tabloyu içermeyen iki kapalı dizin arasında gerçekleşecektir. –

3

Dikkat etmeniz gereken bazı şeyler dizinler, sorgu planı ve istatistiklerdir.

Dizinleri attributeId dizinine yerleştirin. Veya, attributeId anahtardaki ilk sütun olduğunda dizinlerin varolduğundan emin olun (SQL Server, hala 1. sütun değilse bile dizinleri kullanabilir, ancak bu kadar hızlı değil).

Sorgu Çözümleyicisi'nde sorguyu vurgulayın ve planı görmek için^L düğmesine basın. Tabloların nasıl birleştirildiğini görebilirsiniz. Neredeyse her zaman, indeksleri kullanmaktan daha iyidir (bir tablonun yeterince küçük olması durumunda, indekslerin sizi yavaşlatabildiği, ancak şimdilik, zaman indekslerinin% 99'unun iyi olduğunu unutmayın).

Tabloların birleştirildiği sıraya dikkat edin. SQL Server, tablo boyutlarında istatistikleri korur ve hangisinin ilk önce katılacağını belirler. İstatistikleri güncellemek için dahili SQL Server prosedürleri hakkında biraz araştırma yapın - çok uzun zaman geçti, bu yüzden bu bilgiyi kullanmam mümkün değil.

Başlamanız gerekir. Gerçekten, bir veritabanının böyle basit bir sorguyu bile nasıl optimize edebileceği üzerine bir bölüm yazılabilir. yapmak

1

Başka bir şey bu gibi bazı endeksler ekleyin:

attributes.{attributeId, attributeName, attributeValue} 
expressions.{attributeId, expressionID} 

Bu hacky olduğunu! Ancak son çare ise faydalıdır.

Bu, dizinler tarafından "tamamen yanıtlanabilen" bir sorgu planı oluşturur. Genellikle, bir dizin aslında yukarıdaki sorguda bir çift I/O'ya neden olur: biri dizini vurmak için (ör.indeks tarafından atıfta bulunulan gerçek sırayı almak için (attributeName vb.)

"Nitelikler" veya "ifadeler" geniş bir tablodursa bu özellikle yararlıdır. Yani, satırları almak pahalı bir tablo.

Son olarak, sorgunuzu hızlandırmanın en iyi yolu bir WHERE yan tümcesi eklemektir!

+0

bu dizinler ekleme üzerine beni öldürür? WHERE hakkında - Belirli bir isim-değer çiftleri (öznitelikler) kümesi için expressionID (varsa) bulmak için kullanacağım bir geçici tabloyu doldurmak için bu birleştirmeyi kullanıyorum. Yani ben bu süzgecinde – JohnIdol

+0

hızlandırmak için VEYA disjuncts attributeNames + AttributeValues ​​ile filtreleyebileceğimi tahmin ediyorum, ama ben de olsa OR disjuncts eklemek zorundayım çünkü WHERE gibi smt ihtiyacım var (attributeName = 'X' AND attributeValue = 'Y') VEYA (attributeName = 'Z' AND attributeValue = 'W') ... vb. Bu yüzden muhtemelen isim değeri çiftleri ile tablo üzerinden döngü ve bu cümleleri bina – JohnIdol

+0

zaman kaybetmek eklerim Her zaman eklemek için dizinleri bir takas var. Yine (ve ne yazık ki), tek bedenli bir cevap yoktur. Yalnızca bir veya iki dizine sahipseniz ve bunun kümelenmesi yoksa, muhtemelen sizi öldürmeyecektir. Bununla birlikte, bu, belirli bir sorguya yönelik yoğun bir endeks olup, kendi takdirinize bağlı olarak kullanın. – Matt

2

Bahse girerim, sorun, bu geçici tabloya eklenen çok sayıda satırdır. Veritabanındaki her satırın WHERE yan tümcesini ekleyebilmeniz için SELECT veritabanında her satır var mı? Ben doğru şemayı anlamada olsam

+0

için performans önerileri gibi ben bu filtre hızlandırmak için bu sorguya attributeNames + AttributeValues ​​VEYA disjuncts ile filtre olabilir sanırım ama sorun olduğunu '' Deaktüslerini dinamik olarak eklemek zorundayım çünkü nihayetinde almak için WHERE (attributeName = 'X' AND attributeValue = 'Y') VEYA (attributeName = 'Z' AND attributeValue = 'W') ... gibi smt'ye ihtiyacım var. Belirli bir isim-değer çiftleri kümesinin ifade edilmesi. Bu yüzden muhtemelen isim-değer çiftleri ile masa üzerinde döngü ve WHERE yan tümcesi için bu OR disjuncts bina zaman kaybederim. – JohnIdol

+1

Bu hala daha iyi olabilir mi? Ya da bu geçici tabloyu önbelleğe alabilirsin. Bazı orta kademe bellekte önbelleğe alma veya bu geçici tabloyu kalıcı bir tablo haline getirme ve yalnızca diğer tablolardaki satırlar değiştiğinde güncelleştiriliyor mu? – JerSchneid

+0

İndekslerle oynama konusunda önemli geliştirmeler alamıyorsam, bir önceki yorumun açıklamasını dinlediğim gibi birleştirmenin dinamik filtrelemesiyle gideceğim - Önbellekleme tablolarını kullanmaktan kaçınmak istiyorum! – JohnIdol

1

, kendi tablolar tür şuna benzer belirten ediyoruz:

Expressions: PK - ExpressionID, AttributeID 
Attributes: PK - AttributeID 

her PK hala demektir kümelenmiş bir dizin olduğunu varsayarsak İfadeler İfadeleri, İfadeler tablosunda gereklidir. İfadeler tablosunda bir Endeks oluşturmayı düşünebilirsiniz: AttributeID, ExpressionID. Bu, şu anda gerçekleşen Dizin Taramasını durdurmaya yardımcı olur.

+0

anlayışınız doğru. Kümelenmiş dizin dışındaki ifadeler için kümelenmemiş bir dizin ekleme (ExpressionId, AttributeId) var mı? – JohnIdol