首页 > 解决方案 > MySQL Optimizer 对相同查询的意外结果?

问题描述

以下查询按预期工作并使用索引查询需要 0,0481 秒

SELECT 
    geodb_locations.name, 
    geodb_locations.name_url,
    COUNT(user.uid) AS useranzahl 
FROM 
    user 
LEFT JOIN
    geodb_locations ON geodb_locations.id=user.plz
WHERE
    user.freigeben=1 AND
    geodb_locations.adm0='AT'
GROUP BY user.plz
ORDER BY useranzahl DESC
LIMIT 25

解释 在此处输入图像描述

如果在查询中仅更改国家/地区区域设置,则从 AT 到 DE 查询大约需要 2.5 秒并且不使用索引

SELECT 
    geodb_locations.name, 
    geodb_locations.name_url,
    COUNT(user.uid) AS useranzahl 
FROM 
    user 
LEFT JOIN
    geodb_locations ON geodb_locations.id=user.plz
WHERE
    user.freigeben=1 AND
    geodb_locations.adm0='DE'
GROUP BY user.plz
ORDER BY useranzahl DESC
LIMIT 25

解释 在此处输入图像描述

为什么第二个查询的优化器不使用索引以及如何改进查询。2.5 秒太长了..

标签: mysqlquery-optimization

解决方案


如果u.uid不能NULL,请使用COUNT(*)代替COUNT(u.uid)

正如已经指出的,删除LEFT.

添加这些索引:

user:  (freigeben, plz)
geodb_locations:  (adm0, name_url, name)

至于为什么要EXPLAIN更改,... 常量的分布确定触摸表的顺序(奥地利不如德国常见?)或使用哪个索引是很正常的(但有些罕见)。

不管优化如何,这个查询必须为 DE 扫描比 AT 多得多的行;这必须发生在 sort ( ORDER BY) 和LIMIT.

有两件事阻止了很多优化:

  • 引用这WHERE两个表。
  • ORDER BY取决于计算值。

推荐阅读