更新:似乎存在问题(正如各种人所指出的那样),它正在将日期时间字段更改为查询中的日期字段。

使用DATE( all_griefs_tbl.actioned_date太慢了,是否有一种更快的方法而不将actioned_date更改为日期字段或将其拆分为日期和时间字段?

我有2个表,一个表包含状态和datetime字段的记录,另一个是日历表,日期从2008年到2015年。

我想得到的是一个时间段内的每个日期以及每天“接受”的记录数(即使该计数为零),如下所示:

| Date      | number_accepted |
 ----------------------------
 2012-03-01     723
 2012-03-02     723
 2012-03-03     1055
 2012-03-04     1069
 2012-03-05     0
 2012-03-06     615
 2012-03-07     0
 2012-03-08     1072
 2012-03-09     664
 2012-03-10     859
 2012-03-11     0
 2012-03-12     778
 2012-03-13     987


我已经尝试了以下方法,但是对于一小部分数据样本(-1000行)来说,它的速度足够快。我需要在至少60万行上运行良好的工具

SELECT calendar.datefield AS Date,
       COUNT( all_griefs_tbl.actioned_status ) AS total_griefs
FROM all_griefs_tbl
RIGHT JOIN calendar
   ON ( DATE( all_griefs_tbl.actioned_date ) = calendar.datefield )
   AND all_griefs_tbl.actioned_status = 'accepted'
WHERE calendar.datefield < CURDATE( )
GROUP BY calendar.datefield


谢谢

编辑:按要求执行计划

 id select_type     table           type    possible_keys     key               key_len     ref     rows    Extra
 1  SIMPLE          calendar        range   PRIMARY           PRIMARY           3           NULL    1576    Using where; Using index
 1  SIMPLE          all_griefs_tbl  ref     actioned_status   actioned_status   153         const   294975

最佳答案

一些想法...

首先,尽管您声明希望db查询中没有返回任何值的天数,但实际上我将对处理结果集的位置进行此检查。每当进行联接时,查询都会变得更加复杂,并且需要更多内存来处理它们。在这种情况下,我不会把日历表的使用视为关系数据库的一种特殊用途。

编辑:为了澄清,如何调用查询?即是否有(正在开发的)程序正在访问数据库,运行查询并显示结果?如果是这样,我建议让该程序在演示之前处理结果。

其次,如果您承诺加入“联接”,那么您实际上应该在all_griefs_tbl.actioned_date上有一个索引,因为这是您进行联接的列。或者,您可以在calendar.datefield上指定外键。

第三,您是否需要使用功能DATE(all_griefs_tbl.actioned_date)?这不是约会吗? (不确定您的数据类型,但是如果此数据和calendar.datefield不是相同的数据类型,则这似乎是错误的数据库设计。)

编辑:根据您所说的,您可能想将all_griefs_tbl.actioned_date分为两列,即日期列all_griefs_tbl.actioned_date和时间戳列all_griefs_tbl.actioned_time。目前,您正在DATE()中的每一行上运行此all_griefs_tbl函数以进行联接-这将很快使查询变慢。这也将允许您在日期和时间列上都添加索引,这也将提高联接的性能(鉴于您当前的数据库设计,我并不惊讶actioned_date上的索引没有帮助-我d宁愿期望,由于使用了DATE()功能,如果使用当前EXPLAIN列上的索引重新运行actioned_date,则不会使用all_griefs_tbl上的该索引来显示它。)

第四,您可能要考虑all_griefs_tbl.actioned_status中存储了哪些类型的信息。可以将其替换为布尔值吗?在存储和处理数据方面这将更加有效。 (尽管如此,这取决于您的数据库设计。)

编辑:您可以考虑将all_griefs_tbl.action_status更改为较小的数据类型-我希望它当前是varchar,但是您可以轻松地将其更改为单个(或较小的)char数据类型,甚至更改为多个布尔值。但是,我并不希望这成为主要的性能开销,而是取决于项目需求的更复杂的数据库设计决策。

10-07 14:20