2017-12-06 1 views
2

Ich habe diese zwei Version der gleichen Abfrage. Beide produzieren die gleichen Ergebnisse (164 Zeilen). Aber der zweite dauert 0,5 Sekunden, während der erste 17 Sekunden dauert. Kann mir jemand erklären, was hier vor sich geht?Verstehen den Unterschied zwischen zwei Abfragen von Leistungspunkt

TABLE organizations : 11988 ROWS 
TABLE transaction_metas : 58232 ROWS 
TABLE contracts_history : 219469 ROWS 

# TAKES 17 SEC 
SELECT contracts_history.buyer_id as id, org.name, SUM(transactions_count) as transactions_count, GROUP_CONCAT(DISTINCT(tm.value)) as balancing_authorities 
From `contracts_history` 
INNER JOIN `organizations` as `org` 
ON `org`.`id` = `contracts_history`.`buyer_id` 
LEFT JOIN `transaction_metas` as `tm` 
ON `tm`.`contract_token` = `contracts_history`.`token` and `tm`.`field` = '1' 
WHERE `contracts_history`.`seller_id` = '850' 
GROUP BY `contracts_history`.`buyer_id` ORDER BY `balancing_authorities` DESC 


# TAKES .6 SEC 
SELECT contracts_history.buyer_id as id, org.name, SUM(transactions_count) as transactions_count, GROUP_CONCAT(DISTINCT(tm.value)) as balancing_authorities 
From `contracts_history` 
INNER JOIN `organizations` as `org` 
ON `org`.`id` = `contracts_history`.`buyer_id` 
left join (select * from `transaction_metas` where contract_token in (select token from `contracts_history` where seller_id = 850)) as `tm` 
ON `tm`.`contract_token` = `contracts_history`.`token` and `tm`.`field` = '1' 
WHERE `contracts_history`.`seller_id` = '850' 
GROUP BY `contracts_history`.`buyer_id` ORDER BY `balancing_authorities` DESC 

Erklären Ergebnisse: Erste Frage: https://prnt.sc/hjtiw6

Zweite Frage: https://prnt.sc/hjtjjg

Wie basiert auf meinen Debuggen der ersten Abfrage klar war, dass left join-transaction_metas Tisch es langsam machte, So Ich habe versucht, die Zeilen zu begrenzen, anstatt mich an den gesamten Tisch anzuschließen. Es scheint zu funktionieren, aber ich verstehe nicht warum.

+0

warm/kalt Daten Unterschiede? – jarlh

+0

Ich denke, der Grund könnte in der ersten Abfrage sein, mit einer Tabelle 'transaction_metas' zu verbinden, während in der zweiten Abfrage es nicht mit allen Daten, sondern nur aus dieser Tabelle ausgewählt wird. –

+0

@jarlh Sorry Sir. Ich verstehe nicht, was Sie mit heißen/kalten Daten meinen. – Ankit

Antwort

0

Join ist ein Satz von Kombinationen aus Zeilen in Ihren Tabellen. In der ersten Abfrage kombiniert die Engine alle Ergebnisse, um danach zu filtern. Im zweiten Fall wendet man den Filter an bevor er die Kombinationen macht.

Der beste Fall würde Filter in JOIN-Klausel ohne Unterabfrage verwenden. Ähnlich wie folgt aus:

SELECT contracts_history.buyer_id as id, org.name, SUM(transactions_count) as transactions_count, GROUP_CONCAT(DISTINCT(tm.value)) as balancing_authorities 
From `contracts_history` 
INNER JOIN `organizations` as `org` 
ON `org`.`id` = `contracts_history`.`buyer_id` 
    AND `contracts_history`.`seller_id` = '850' 
LEFT JOIN `transaction_metas` as `tm` 
ON `tm`.`contract_token` = `contracts_history`.`token` 
    AND `tm`.`field` = 1 
GROUP BY `contracts_history`.`buyer_id` ORDER BY `balancing_authorities` DESC 

Hinweis: Wenn Sie die Größe der Join-Tabellen zu reduzieren, indem sie mit Subqueries Filterung kann es ermöglichen, dass die Zeilen in den Puffer passen. Netter Trick zu kleinem Pufferlimit.

Eine bessere Erklärung: https://dev.mysql.com/doc/refman/5.5/en/explain-output.html

+0

Dies dauert genau die gleiche Zeit wie die erste Abfrage, die ich hatte d. H. 17.0806 Sekunden – Ankit

+0

Ihre Erklärung ergibt Sinn. und deshalb habe ich die zweite Abfrage erstellt. Aber aus irgendeinem Grund glaube ich, dass MySql das selbst tun sollte. Ich meine Wir haben die Bedingung auf dem Haupttisch, die seine Aufzeichnung begrenzt. Sollte es nicht sein, diese Datensätze nur zu transaction_metas entsprechenden Datensätzen mit Index oder etwas beizutreten. auch wenn nicht 17 sec zu viel für 58232 Zeilen sind – Ankit

+0

Haben Sie die Fremdschlüssel mit Innodb-Tabellenmodus erstellt? –

Verwandte Themen