从性能点

时间:2017-12-06 12:09:23

标签: mysql sql

我有两个版本的相同查询。两者都产生相同的结果(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 jointransaction_metas表使它变慢,所以我试图限制其行而不是加入到整个表。它似乎有用,但我不明白为什么。

1 个答案:

答案 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