避免全索引扫描

时间:2018-11-29 18:04:40

标签: mysql query-optimization

我使用MySQL employees - test db中的测试数据库 我想优化查询

SELECT emp_no, SUM(salary)
FROM salaries
WHERE from_date < '1999-01-01'
group by emp_no;

查询费用:287790

哪些索引可以帮助我?

我尝试使用emp_no和薪金,emp_no和from_date创建索引,但是没有结果。有完整的扫描索引。

还尝试使用OVER(PARTITION BY)代替GROUP BY

SELECT emp_no, SUM(salary) OVER (PARTITION by emp_no)
FROM salaries  
WHERE from_date < '1999-01-01'; 

避免实例进行全索引扫描,或使用OVER代替GROUP BY

2 个答案:

答案 0 :(得分:0)

要获得一个避免进行全面扫描的执行计划,MySQL将需要一个以from_date作为前导列的索引。

最佳地,索引将包含查询中引用的所有其他列,以避免在基础数据页中查找值。

请注意,如果执行计划使用该索引,则它将需要调用“使用文件排序”操作来满足GROUP BY。

答案 1 :(得分:0)

这取决于您运行的版本。

较旧的版本:INDEX(from_date, emp_no, salary)正在“覆盖”并且将对部分索引进行“范围”扫描。但是GROUP BY可能涉及某种排序。

较新的版本:INDEX(emp_no, from_date, salary)也在“覆盖”中,但是可以跳过索引而不必触摸每一行。这样可以避免排序。

这是另一件事要测试:

SELECT emp_no,
       ( SELECT SUM(salary) FROM salaries
             WHERE emp_no = e.emp_no 
               AND from_date < '...')
    FROM employees AS e

注意:我假设employees每位员工有一行,而不像salaries?该方法避免了GROUP BY,但具有相关子查询的开销。现在salaries需要INDEX(emp_no, from_date, salary) -以的顺序进行,并且每次都在索引中进行较小的范围扫描。