Php Mysql选择查询性能变差

Php Mysql选择查询性能变差,php,mysql,sql,select,union,Php,Mysql,Sql,Select,Union,我得到了一个mysql查询,它选择了一天中每小时的所有点击。 在我们的数据库中有很多点击条目之前,这个查询一直运行良好。现在它有时需要几秒钟(最多9秒钟!)来请求数据 查询是: SELECT h.clickHour, COUNT(clicktime) AS c FROM ( SELECT 0 AS clickHour UNION ALL SELECT 1 UNION ALL SELECT 2 UNION A

我得到了一个mysql查询,它选择了一天中每小时的所有点击。 在我们的数据库中有很多点击条目之前,这个查询一直运行良好。现在它有时需要几秒钟(最多9秒钟!)来请求数据

查询是:

SELECT h.clickHour, COUNT(clicktime) AS c
      FROM ( SELECT 0 AS clickHour
             UNION ALL SELECT 1
             UNION ALL SELECT 2
             UNION ALL SELECT 3
             UNION ALL SELECT 4
             UNION ALL SELECT 5
             UNION ALL SELECT 6
             UNION ALL SELECT 7
             UNION ALL SELECT 8
             UNION ALL SELECT 9
             UNION ALL SELECT 10
             UNION ALL SELECT 11
             UNION ALL SELECT 12
             UNION ALL SELECT 13
             UNION ALL SELECT 14
             UNION ALL SELECT 15
             UNION ALL SELECT 16
             UNION ALL SELECT 17
             UNION ALL SELECT 18
             UNION ALL SELECT 19
             UNION ALL SELECT 20
             UNION ALL SELECT 21
             UNION ALL SELECT 22
             UNION ALL SELECT 23 ) AS h
    INNER JOIN links l ON l.user_id = 1
    LEFT OUTER
      JOIN clicks
        ON EXTRACT(HOUR FROM clicks.clicktime) = h.clickHour
          AND DATE(clicks.clicktime) = '2014-09-21'
          AND clicks.link_id = l.id
    GROUP
        BY h.clickHour
我有这些工会,因为我需要点击每小时也空小时。。。 请帮忙


好的,我们讨论的是0到数千行的表点击。点击时间被保存为一个时间戳,每次点击都会得到一个唯一的id。我发现工会的事情很糟糕,我必须改变它

我现在尝试的是选择一天中按小时分组的所有单击(单击时间): 但是当我这样做的时候,我得到了太多的结果,比如10倍,那么应该是这样。

你索引了吗

点击表:点击时间,链接id


Links table:id,user\u id

我会像这样重写查询:

SELECT h.clickHour
     , IFNULL(d.clickCount,0) AS c
  FROM ( SELECT 0 AS clickHour UNION ALL SELECT  1 UNION ALL SELECT  2
           UNION ALL SELECT  3 UNION ALL SELECT  4 UNION ALL SELECT  5
           UNION ALL SELECT  6 UNION ALL SELECT  7 UNION ALL SELECT  8
           UNION ALL SELECT  9 UNION ALL SELECT 10 UNION ALL SELECT 11
           UNION ALL SELECT 12 UNION ALL SELECT 13 UNION ALL SELECT 14
           UNION ALL SELECT 15 UNION ALL SELECT 16 UNION ALL SELECT 17
           UNION ALL SELECT 18 UNION ALL SELECT 19 UNION ALL SELECT 20
           UNION ALL SELECT 21 UNION ALL SELECT 22 UNION ALL SELECT 23 
       ) h
  LEFT
  JOIN ( SELECT EXTRACT(HOUR FROM c.clicktime) AS clickHour
              , SUM(1) AS clickCount
           FROM clicks c
           JOIN links l
             ON l.user_id = 1
            AND l.id = c.link_id
          WHERE c.clicktime >= '2014-09-21'
            AND c.clicktime <  '2014-09-21' + INTERVAL 1 DAY 
          GROUP BY EXTRACT(HOUR FROM c.clicktime)
       ) d
    ON d.clickHour = h.clickHour
如果
id
links
表上是唯一的(或主键),则此索引可能不会提供任何性能优势:

ON links (id, user_id)
如果使用覆盖索引,解释输出应显示“使用索引”


我看不到解决“使用文件排序”操作的方法,除非在
clicks
表中添加一列来存储截断为小时的clickTime。有了这样一个列,再加上一个适当的索引,我们就有可能使用索引优化
groupby
操作,从而避免“usingfilesort”操作。

为什么不在一个表中用一个列指定小时?我们需要了解更多信息。我们说的是几排?您是否使用了
解释
?你有索引设置吗?到目前为止,您尝试了什么?好的,那么我们谈论的是0到数千行。点击时间被保存为一个时间戳,每次点击都会得到一个唯一的id。我发现工会的事情很糟糕,我必须改变它。对不起,我不知道解释是什么?@jab73:
EXPLAIN
为我们提供了关于SELECT语句的查询执行计划的信息。在SELECT语句前面加上关键字EXPLAIN,然后执行它,您将得到一个结果集,其中包含有关MySQL将如何执行查询的详细信息。解释EXPLAIN的输出确实需要了解优化器可以使用哪些操作,以及什么影响优化器选择特定操作。参考资料:@jab73:我在回答中的建议是基于对您的表的大量假设,以及对MySQL优化器工作原理的一些了解(特别是它的工作方式是有限的,与其他RDBMS中的优化器相比,它看起来几乎是死气沉沉的),但这些限制也使得它相当可预测,在某些情况下比Oracle和SQL Server更可预测。)调整MySQL查询是科学、历史、艺术和魔法的混合。是的,表链接获得了用户id,表单击获得了链接id,以提高索引重要列所需的性能。由于在where子句中使用了clicktime来区分日期记录,因此可能需要对其进行适当的索引。EXPLAIN是指查询语法,它可以帮助您确定哪些部分可以改进(性能)是的,前导列为
clickTime
的索引对某些查询是有益的,但MySQL不能利用该索引上的范围扫描操作来满足
DATE(clickTime)
上的谓词;MySQL必须在表中的每个翻转行上计算该表达式(调用DATE函数)。如果我们重写这个谓词,使其位于“bare”列上
clickTime>=x和clickTime
,那么MySQL就可以有效地利用索引了。我明白了。我已经怀疑过了。但mySQL是否可以将“日期(clicks.clicktime)”放在一个索引中?因为我记得我在Oracle中用一个函数(列)完成了它。谢谢你提供的信息。@matrono:噢,我们多么渴望MySQL中有Oracle风格的基于函数的索引。但是,唉,没有。MySQL不支持基于函数的索引。MySQL中的解决方法是在表中定义一列来存储函数/表达式的结果,将其具体化为实际列,然后对该列进行索引。在查询中,我们引用了该列(该列与源列不“同步”有一点混乱……基于Oracle函数的索引通过自动维护该列而避免了这一点,并且不允许任何人篡改索引中存储的内容。)非常感谢此查询做出了更改!现在请求的时间是0.0007秒,而不是9秒!
ON links (id, user_id)