2017-07-28 121 views
6

İki tablom var. 100.000 satır olan order_details ve 10,000 satır olan outbound.Bu basit birleştirme sorgusu neden bir alt sorgu ile önemli ölçüde daha hızlıdır?

Onlara her ikisinde de bir VARCHAR (50) olan order_number adlı bir sütuna katılmam gerekiyor. order_number, giden tabloda benzersiz değil.

CREATE TABLE `outbound` (
    `outbound_id` int(12) NOT NULL, 
    `order_number` varchar(50) NOT NULL 
) ENGINE=InnoDB DEFAULT CHARSET=utf8; 

CREATE TABLE `order_details` (
    `order_details_id` int(12) NOT NULL, 
    `order_number` varchar(50) NOT NULL 
) ENGINE=InnoDB DEFAULT CHARSET=utf8; 

Bu benim ilk sorgu olduğunu ve çalıştırmak için 60 yıldan saniye sürer:

SELECT o.order_number 
FROM outbound o 
INNER JOIN order_details od 
    ON o.order_number = od.order_number 

Bu sorgu aynı sonuçları alır ve çalıştırmak için bir saniyeden daha kısa sürer:

SELECT o.order_number 
FROM outbound o 
INNER JOIN 
(
    SELECT order_number 
    FROM order_details 
) od 
ON (o.order_number = od.order_number) 

Bu benim için şaşırtıcıdır çünkü genellikle alt sorgular önemli ölçüde daha yavaştır.

(hala anlamış öğreniyorum) alt sorgu sürümü dizin kullanıyor ve bu indeks auto_key0 olduğunu, bir derived2 tablosu kullanır göstermektedir EXPLAIN Running. Bunun neden önemli bir fark yarattığını anlamak için bunu nasıl yorumlayacağımı bilmek yeterince bilgim yok.

Bu sorguları komut satırında çalıştırıyorum.

Linux (x86_64) CentOS için MySQL Ver 14.14 Dağıtımı 5.6.35 çalıştırıyorum.

Neden bu basit bir alt sorgu ile çok daha hızlı sorgu katılmak edilir: Özetle

?

+0

MySQL'in bozuk optimize edici? “EXISTS” veya “IN” ile de mi karşılaştırdınız? '' Ya da ' O, giden DAN o.order_number SELECT ( o.order_number = od.order_number OD OLARAK Order_Details GELEN ORDER_NUMBER SEÇ) MEVCUT O, giden DAN o.order_number Where ( SELECT ORDER_NUMBER order_number FROM order_details) – dnoeth

+0

@ İlk sorgunun bir dakikadan uzun sürdüğünü anladığından, ikinci sorgu anlık olur. – Goose

+1

Dediğim gibi, iyi bir iyileştirici dört benzer davranmalıdır (aslında order_details.orde_number' benzersiz olmadığında birleşimler farklı bir sonuç alabilir). – dnoeth

cevap

5

MySQL bilgim çok sınırlıdır. Ama düşüncelerim:

Tablonuzun indeksi yok. Ardından, birleştirmenin ilk tablonun her satırı için karşılaştırmak için ikinci tablonun tamamını okuması gerekir.

Alt sorgu ikinci tabloyu bir kez okur ve bir dizin oluşturur, ardından ilk tablonun her satırı için ikinci tablonun tamamını okumasına gerek yoktur. Sadece daha hızlı olan endeksi kontrol etmek zorunda.

Sorumluluk alıp almadığımı doğrulamak için, iki tablonuzdaki sütun düzeni_sayısı için dizin oluşturmayı deneyin (INDEX ... CREATE) ve bu iki sorguyu tekrar çalıştırın. İlk sorgunuz sadece bir dakika yerine bir saniyeden az sürmelidir.

+0

Verileri test etmek için veriyi aşağı çekmek için bir ağrım vardı, ama yaptığınız zaman cevabınızın doğru olduğunu buldum. Cevabınız için teşekkürler, mantıklı. – Goose