我有两个版本的相同查询。两者都产生相同的结果(164行)。但是第二个需要0.5秒,而第一个需要17秒。有人能解释一下这里发生了什么吗?
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
解释结果: 第一个查询:https://prnt.sc/hjtiw6
第二次查询:https://prnt.sc/hjtjjg
根据我对第一个查询的调试,显然left join
到transaction_metas
表使它变慢,所以我试图限制其行而不是加入到整个表。它似乎有用,但我不明白为什么。
答案 0 :(得分:0)
Join是表中行的一组组合。记住,在第一个查询中,引擎将所有结果组合在一起以便过滤。在第二种情况下,它在尝试进行组合之前应用过滤器。
最好的情况是在没有子查询的情况下使用JOIN子句中的过滤器。 很像这样:
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
注意:通过使用子查询进行过滤来减小连接表的大小时,可能允许行适合缓冲区。小缓冲区限制的好方法。
更好的解释: https://dev.mysql.com/doc/refman/5.5/en/explain-output.html