简单查询缓慢

简单查询缓慢

问题描述:

无论如何,要获得更好的性能。简单查询缓慢

SELECT fdyofmth, SUM(total_restored) AS total_restored 
FROM sum_restored 
WHERE fdyofmth BETWEEN '2010-11-01' AND '2011-11-01' 
GROUP BY fdyofmth 
ORDER BY fdyofmth DESC 

结果需要3秒。

+------------+----------------+ 
| fdyofmth | total_restored | 
+------------+----------------+ 
| 2011-11-01 |   39793 | 
| 2011-10-01 |   52367 | 
| 2011-09-01 |   52141 | 
| 2011-08-01 |   56515 | 
| 2011-07-01 |   54668 | 
| 2011-06-01 |   54874 | 
| 2011-05-01 |   60025 | 
| 2011-04-01 |   60005 | 
| 2011-03-01 |   63856 | 
| 2011-02-01 |   64472 | 
| 2011-01-01 |   58943 | 
| 2010-12-01 |   57005 | 
| 2010-11-01 |   55731 | 
+------------+----------------+ 

EXPLAIN结果 -

+----+-------------+--------------+------+---------------+------+---------+------+--------+----------------------------------------------+ 
| id | select_type | table  | type | possible_keys | key | key_len | ref | rows | Extra          | 
+----+-------------+--------------+------+---------------+------+---------+------+--------+----------------------------------------------+ 
| 1 | SIMPLE  | sum_restored | ALL | NULL   | NULL | NULL | NULL | 752660 | Using where; Using temporary; Using filesort | 
+----+-------------+--------------+------+---------------+------+---------+------+--------+----------------------------------------------+ 
1 row in set 

我试图把它实际上是由它慢一倍fdyofmth的关键。

任何帮助将不胜感激。

谢谢。

+0

这些字段的类型是什么。你可以粘贴CREATE吗?你在这张桌上有多少条记录?速度有多慢,您可以粘贴执行时间吗? –

+0

“fdyofmth”(本身)的索引将有所帮助。有一个吗? – wallyk

+0

@NedretRecep我现在不在工作,所以我不能粘贴CREATE,但字段是“DATE - fdyofmth”和“INT - total_restored”。正如我所说,需要3秒才能显示结果,而在fdyofmth上的索引需要6秒 - 根据解释计划,此表中的总行数为752K。谢谢。 – mybigman

试试这个: 如果日期是不一样的,那么

 
SELECT fdyofmth, SUM(total_restored) AS total_restored 
FROM sum_restored 
WHERE fdyofmth >= '2010-11-01' AND fdyofmth <= '2011-12-01' 
GROUP BY fdyofmth 
ORDER BY fdyofmth DESC 

希望它可以帮助

+0

感谢您的回复我已经尝试过了,结果几乎相同:( – mybigman

根据您的EXPLAIN结果,查询不使用任何索引。你需要建立在fdyofmth指数:

ALTER TABLE sum_restored ADD INDEX fdyofmth_index (fdyofmth); 

或者另一种意见认为=):

SELECT 
    SUM (IF(fdyofmth = '2010-11-01', total_restored, NULL)) as `2010-11-01`, 
    SUM (IF(fdyofmth = '2010-12-01', total_restored, NULL)) as `2010-12-01`, 
    SUM (IF(fdyofmth = '2011-01-01', total_restored, NULL)) as `2011-01-01`, 
    SUM (IF(fdyofmth = '2011-02-01', total_restored, NULL)) as `2011-02-01`, 
    SUM (IF(fdyofmth = '2011-03-01', total_restored, NULL)) as `2011-03-01`, 
    SUM (IF(fdyofmth = '2011-04-01', total_restored, NULL)) as `2011-04-01`, 
    SUM (IF(fdyofmth = '2011-05-01', total_restored, NULL)) as `2011-05-01`, 
    SUM (IF(fdyofmth = '2011-06-01', total_restored, NULL)) as `2011-06-01`, 
    SUM (IF(fdyofmth = '2011-07-01', total_restored, NULL)) as `2011-07-01`, 
    SUM (IF(fdyofmth = '2011-08-01', total_restored, NULL)) as `2011-08-01`, 
    SUM (IF(fdyofmth = '2011-09-01', total_restored, NULL)) as `2011-09-01`, 
    SUM (IF(fdyofmth = '2011-10-01', total_restored, NULL)) as `2011-10-01`, 
    SUM (IF(fdyofmth = '2011-11-01', total_restored, NULL)) as `2011-11-01` 
FROM sum_restored; 
+0

会更快吗?即使您拥有索引,查询也会遍历所有数据 –

+0

@newtover正如我在我的解释问题我确实在fdyofmth上放了一个索引,但是这样做使查询从3秒到6秒让我感到困惑:( – mybigman

+0

@ james-xu,该字段在'WHERE'条件下使用,如果它切断在BETWEEN中比较的一个重要部分,但你似乎是对的:条件是非常宽泛,数据太多 – newtover

,我认为它是缓慢的,因为你有这么多的数据,你的SQL都必须经过所有的数据(不从整个数据集挑一个),所以index不能帮助这里。

笔者建议选择是使用并行:

  1. 添加索引由@newtover
  2. 使用的建议12个线程来检索每个月的效果。

或者更简单:

只是预先计算出结果到另一个表, 查询时,从该表中查询。

+0

我喜欢预先计算的想法值和存储在另一个表中,但问题是这些日期是随机的基于用户选择。他们也可以将过滤器应用到表中的其他列,这也会影响结果,所以我不认为它会成为可能吗?令我感到惊讶的是,对ORACLE DB的相同查询大约为500毫秒: - /奇怪还是什么? – mybigman

+0

有一些设置可以调整,例如,如果您使用的是** innodb **,最重要的设置可能是'innodb_buffer_pool_size',大多数情况下您应该将大部分内存分配给它。 –

您应该解决此外部查询更改。

  • 创建一个表来保存准备计算汇总每个过去一个月
  • 砍下表的很多的大小。每年或每月或每行的另一个表格更改。