MySQL: Sol birleşim ve iç birleşim arasında hangi birleşim daha iyidir


11

Eğer hepsi aynı sonucu verirse hangi birleşim daha iyi performans gösterir? Örneğin, iki tablo employees(emp_id,name, address, designation, age, sex)ve var work_log(emp_id,date,hours_wored). Bazı özel sonuçlar elde hem etmek inner joinve left joinaynı sonucu verir. Ancak, hala sadece bu soru ile sınırlı olmayan bazı şüphelerim var.

  • hangi sonuç daha verimli, hangisi aynı sonuç değerlerinde tercih edilmeli?
  • Birleştirmeyi uygularken dikkate alınması gereken diğer faktörler nelerdir?
  • İç birleşim ile çapraz birleşim arasında herhangi bir ilişki var mı?

Yanıtlar:


15

"Daha iyi" veya "daha kötü" birleştirme türü yoktur. Farklı anlamları vardır ve buna bağlı olarak kullanılmaları gerekir.

Senin durumunda, muhtemelen hiçbir work_log çalışanlarına (yani tabloda hiç satırlar) yok, bu yüzden LEFT JOINve JOINsonuçlarda eşdeğer olacaktır. Ancak, böyle bir şey (kayıtlı çalışma_log olmayan yeni bir çalışan) olsaydı, JOINo çalışanı atlar, sol katılım (ilk tablosu çalışanlar) hepsini gösterir ve eğer varsa work_log alanlarındaki boş değerleri gösterir. eşleşmez.

JOIN tiplerinin görsel açıklaması

Yine, performans doğruluğu sorgulamak için ikincil bir şeydir. Bazı insanlar LEFT JOINs kullanmamanız gerektiğini söylüyor . Bir LEFT JOIN, optimize ediciyi sorguyu belirli bir sırada yürütmeye zorlayarak bazı durumlarda bazı optimizasyonları (tablo yeniden sıralama) önler. İşte bir örnek . Ancak bir INNER JOIN doğası gereği daha kötü olmadığından doğruluk / anlam feda edilirse birini diğerinden seçmemelisiniz. Her zamanki optimizasyonların geri kalanı her zamanki gibi geçerlidir.

Özetle, LEFT JOINgerçekten demek istiyorsan kullanmayın INNER JOIN.

MySQL CROSS JOIN, INNER JOINve JOINaynıdır. Standart ve anlamsal olarak, a CROSS JOIN, INNER JOINbir ONcümlesizdir, böylece tablolar arasındaki her satır kombinasyonunu elde edersiniz.

Wikipedia'daki tüm semantik birleştirme türlerine örnekler var . Uygulamada, MySQL'de sadece JOINve yazma eğilimindeyiz LEFT JOIN.


1
Gr8 açıklaması @jynus. Sorularıma sadece sizden cevap aldığım şanslı.
ursitesion

1 ilgili grafik 1000 kelimeden daha iyidir. Onu sen mi yaptın?
Fr0zenFyr

Hayır, yapmadım, ilişkilendirme görüntünün alt kısmında codeproject.com/Articles/33052/... : katıldığında temsil etmek şemalar Venn kullanarak cebirsel biçimsellikle kadar eski olmasına rağmen - en.wikipedia.org/wiki/Relational_algebra
jynus

Ben bir dizi yorum başladı sonra tüm aşağı kaynar fark - sorgunuza bağlıdır. Benden +1!
iheanyi


0

Hepsi aynı sonucu veriyorsa hangi birleştirme daha iyi performans gösterir?

Önceki cevabın yanı sıra bildiğim kadarıyla MySQL de aynı performansa sahip olacak şekilde optimize edildi.

İyi endekslerle, örneğin, filtrelenecek JOINvs LEFT JOIN+ WHEREmaddesi aynı şey olacaktır. Optimizasyon ve İnsan Okuma , çok sayıda birleşim içeren büyük sorgular için anlamlıdır.

İyi dizinler ve önbellek kullanmak daha önemlidir.

Optimizasyon sürecinin iyi bir açıklamasını buradan okuyabilirsiniz:

Sorgu Optimizasyonu Süreci : Bir sorgu genellikle birçok farklı şekilde yürütülebilir ve aynı sonucu üretebilir. Optimize edicinin işi en iyi seçeneği bulmaktır.


0

Benim için aynı değil, MySql 5.7 8 vCPU, 52 GB RAM

Aşağıdaki sorgu ~ 30 saniye sürüyor, neden olduğundan emin değilim

İşlemler tablosunda 24.257.151 kayıt bulunmaktadır

Faaliyet tablosunun 18.603.665 kaydı var

Alımlar tablosunda 13.911.705 kayıt var

Gerekli tüm dizinler mevcut

SELECT
    `trx`.`transaction_pk`,
    `trx`.`created`,
    `trx`.`updated`,
    `p`.`amount`,
    `trxst`.`name`,
    COALESCE ( a.units, 0 ) AS units
FROM
    `transaction` AS `trx`
    INNER JOIN `transaction_sub_type` AS `trxst` ON  `trx`.`transaction_sub_type_fk`= `trxst`.`transaction_sub_type_pk`
    left JOIN `activity` AS `a` ON `a`.`transaction_fk` = `trx`.`transaction_pk`
    LEFT JOIN `purchases` AS `p` ON `p`.`transaction_fk` = `trx`.`transaction_pk` 
WHERE
    `trx`.`entity_fk` IN ( 1234) 
    AND `trx`.`transaction_sub_type_fk` IN (
    2, 4, 5, 15, 16, 33, 37, 38, 85, 86, 87, 88, 102, 103 
    ) 
ORDER BY
    `trx`.`transaction_pk` DESC LIMIT 100 OFFSET 0;

Aşağıdaki satırı değiştirdikten sonra:

INNER JOIN `transaction_sub_type` AS `trxst` ON  `trx`.`transaction_sub_type_fk`= `trxst`.`transaction_sub_type_pk`

LEFT JOIN ile

LEFT JOIN `transaction_sub_type` AS `trxst` ON  `trx`.`transaction_sub_type_fk`= `trxst`.`transaction_sub_type_pk`

aynı sorgu ~ 0.046s alır

Daha önce açıklayın:

1   SIMPLE  trxst       ALL PRIMARY             101 37.62   Using where; Using temporary; Using filesort
1   SIMPLE  trx     ref transaction_sub_type_fk,entity_fk   transaction_sub_type_fk 4   trxst.transaction_sub_type_pk   2548    0.36    Using where
1   SIMPLE  a       ref transaction_fk  transaction_fk  4   trx.transaction_pk  1   100 
1   SIMPLE  p       ref transaction_fk  transaction_fk  4   trx.transaction_pk  1   100 

Sonra açıklayın:

1   SIMPLE  trx     ref transaction_sub_type_fk,entity_fk   entity_fk   4   const   81474   83.65   Using where
1   SIMPLE  trxst       eq_ref  PRIMARY PRIMARY 4   trx.transaction_sub_type_fk 1   100 
1   SIMPLE  a       ref transaction_fk  transaction_fk  4   trx.transaction_pk  1   100 
1   SIMPLE  p       ref transaction_fk  transaction_fk  4   trx.transaction_pk  1   100 
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.