优化运行大约30秒的MySQL查询

优化运行大约30秒的MySQL查询,mysql,sql,Mysql,Sql,我正在运行一个查询,以获取每个用户在一个日期范围内输入的注释总数。这是我正在运行的查询: SELECT SQL_NO_CACHE COUNT(notes.user_id) AS "Number of Notes" FROM csu_users JOIN notes ON notes.user_id = csu_users.user_id WHERE notes.timestamp BETWEEN "2013-01-01" AND "2013-01-31" AND

我正在运行一个查询,以获取每个用户在一个日期范围内输入的注释总数。这是我正在运行的查询:

SELECT SQL_NO_CACHE 
    COUNT(notes.user_id) AS "Number of Notes"

FROM csu_users

JOIN notes      ON notes.user_id    = csu_users.user_id

WHERE notes.timestamp BETWEEN "2013-01-01" AND "2013-01-31"
AND notes.system = 0

GROUP BY csu_users.user_id
关于我的设置的一些注意事项:

  • 查询运行需要30到35秒,这对于我们的系统来说太长了
  • 这是一个InnoDB表
  • notes
    表约为1GB,约有3000000行
  • 我故意使用
    SQL\u NO\u CACHE
    来确保准确的基准测试
EXPLAIN SELECT
的输出如下所示(我已尽力将其格式化):

我应用了以下索引:

注释

  • 主键-
    id
  • item\u id
  • user\u id
  • 时间戳
    (注意:这实际上是一个
    日期时间
    。名称只是误导,对不起!)
  • 系统
csu\u用户

  • 主键-
    id
  • user\u id

有什么办法可以加快速度吗?谢谢大家!

如果我没有弄错的话,通过将时间戳转换为字符串表示,您正在失去该列上索引的所有优势。尝试在比较中使用时间戳值

是否需要
csu\u用户
表?如果关系为1-1且用户id始终存在,则可以改为运行此查询:

SELECT COUNT(notes.user_id) AS "Number of Notes"
FROM notes 
WHERE notes.timestamp BETWEEN "2013-01-01" AND "2013-01-31" AND notes.system = 0
GROUP BY notes.user_id
即使情况并非如此,您也可以在聚合和筛选之后进行连接,因为所有条件都在
notes

select "Number of Notes"
from (SELECT notes.user_id, COUNT(notes.user_id) AS "Number of Notes"
      FROM notes 
      WHERE notes.timestamp BETWEEN "2013-01-01" AND "2013-01-31" AND notes.system = 0
      GROUP BY notes.user_id
     ) n join
     csu_users cu
     on n.user_id = cu.user_id

为了完成答案,解决方案是省略DATE_格式,直接使用notes.timestamp。我过去曾尝试过这种方法,但又运行了一次。
WHERE
子句现在的内容是:
WHERE notes.timestamp介于“2013-01-01”和“2013-01-31”
之间,运行仍然需要30秒:-(注意:这可能有点误导,我知道它的名称是
timestamp
,但它实际上并不是作为
时间戳存储的,而是作为
DATETIME
存储的(对不起,我继承了这张桌子)同样,您需要将其保持为原始数据类型,因此您必须为结束日期和开始日期创建2个datetime值,然后将notes.timestamp与这些变量进行比较,而不将notes.timestamp转换为字符串,日期格式就是这样。您应该只使用date\u格式来显示用户友好的日期,而不是在条件下,尤其是有这么大的表。像这样?
stru-TO-u-DATE(“2013-01-01”,%Y-%m-%d”)和stru-TO-u-DATE(“2013-01-31”,%Y-%m-%d”)之间的notes.timestamp在哪里?
-相同的结果,30秒的查询…如果不重要的话,为什么不显示没有g_用户和g_人的SQL查询?我们的生活容易吗?:)抱歉,说得好!我现在就编辑它以简化问题。尝试使用(NOLOCK)@Luv。你能澄清一下位置/方式吗?这是一个InnoDB表。与你的问题无关,但使用时间戳和中间值可能会给你错误的答案。使用>=date1和select "Number of Notes" from (SELECT notes.user_id, COUNT(notes.user_id) AS "Number of Notes" FROM notes WHERE notes.timestamp BETWEEN "2013-01-01" AND "2013-01-31" AND notes.system = 0 GROUP BY notes.user_id ) n join csu_users cu on n.user_id = cu.user_id