解释MySQL解释执行计划数学,两个计划之间的差异

解释MySQL解释执行计划数学,两个计划之间的差异,mysql,performance,explain,sql-execution-plan,Mysql,Performance,Explain,Sql Execution Plan,我有一个基本的MySQL性能问题需要解释。我有两个查询返回相同的结果,我试图理解如何理解执行计划的解释 表中有50000条记录,我正在进行记录比较。我的第一个查询需要18.625秒才能运行。解释计划如下 id select_type table type possible_keys key key_len ref rows filtered Extra --

我有一个基本的MySQL性能问题需要解释。我有两个查询返回相同的结果,我试图理解如何理解执行计划的
解释

表中有50000条记录,我正在进行记录比较。我的第一个查询需要18.625秒才能运行。解释计划如下

id  select_type table   type    possible_keys                   key         key_len ref                                 rows    filtered    Extra
--------------------------------------------------------------------------------------------------------------------------------------------------------------------
1   SIMPLE      a       ALL     NULL                            NULL        NULL    NULL                                49520   100.00  
1   SIMPLE      b       ref     scoreEvent,eventScore           eventScore  4       olympics.a.eventId                  413     100.00      Using where; Using index; Not exists
1   SIMPLE      c       ref     PRIMARY,scoreEvent,eventScore   scoreEvent  8       olympics.a.score,olympics.a.eventId 4       100.00      Using where; Using index; Not exists
我的下一个查询需要0.106秒才能运行

id  select_type table       type    possible_keys   key     key_len     ref     rows    filtered    Extra
-----------------------------------------------------------------------------------------------------------------------------------
1   PRIMARY     <derived2>  ALL     NULL            NULL    NULL        NULL    50000   100.00      Using temporary; Using filesort
2   DERIVED     results     ALL     NULL            NULL    NULL        NULL    49520   100.00      Using filesort
第一个查询

SELECT a.resultId, a.eventId, a.athleteId, a.score
FROM results a 

-- Find records with matching eventIds and greater scores
LEFT JOIN results b 
ON b.eventId = a.eventId 
AND b.score > a.score

-- Find records with matching scores and lesser testIds
LEFT JOIN results c
ON c.eventId = a.eventId
AND c.score = a.score
AND c.resultId < a.resultId

-- Filter out all records where there were joins
WHERE c.resultId IS NULL 
AND b.resultId IS NULL;
我还注意到,如果我删除索引
eventScore
,查询将下降到2.531秒,执行计划不会有太大变化,但可能的_键的顺序会发生变化,并且不会
对表
b
使用索引(忽略每次更改架构时生成数据的行数的细微变化)


不要太相信EXPLAIN的“rows”语句,就像mysql文档中的那样:“估计要检查的行数”()


也许更新索引统计信息会给你一个更好的估计(优化表)

事实上,当你看到你不应该乘法,而是求和这些数字时。 在您的情况下,比较(49520 x 413 x 4)和(50000+49520)

一般规则很简单:汇总所有段(派生段、主段)并在每个段中乘以行

id select_type  ... rows
1  PRIMARY           1
1  PRIMARY           2
2  DERIVED           3
2  DERIVED           4
3  DERIVED           5
3  DERIVED           6

复杂性是:1*2+3*4+5*6

您可能想发布实际的查询和架构。仅从解释输出就很难理解这一点。问得好!似乎两个查询是不同的:第一个查询使用很少的条件过滤数据,但第二个查询没有应用任何过滤条件。是的,没有v,我的猜测是正确的查看您的查询。第一个查询有多个WHERE条件,因此需要更多的执行时间。您不必在每次查询后运行
重置查询缓存
,只需将
SQL\u NO\u缓存
添加到查询中即可。即
从表中选择SQL\u NO\u缓存*
SELECT resultId, athleteId, eventId, score
FROM (
  SELECT resultId, athleteId, eventId, score
  FROM results
  ORDER BY eventId, score DESC, resultId
) AS a
GROUP BY eventId;
id  select_type table   type    possible_keys               key         key_len ref                                 rows    filtered    Extra
--------------------------------------------------------------------------------------------------------------------------------------------------------------------
1   SIMPLE      a       ALL     NULL                        NULL        NULL    NULL                                47457   100.00  
1   SIMPLE      b       ref     eventId,scoreEvent          eventId     4       olympics.a.eventId                  659     100.00      Using where; Not exists
1   SIMPLE      c       ref     PRIMARY,eventId,scoreEvent  scoreEvent  8       olympics.a.score,olympics.a.eventId 5       100.00      Using where; Using index; Not exists
id select_type  ... rows
1  PRIMARY           1
1  PRIMARY           2
2  DERIVED           3
2  DERIVED           4
3  DERIVED           5
3  DERIVED           6