0

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

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,约 3,000,000 行
  • 我故意使用SQL_NO_CACHE以确保准确的基准

的输出EXPLAIN SELECT如下(我已尽力格式化):

id  select_type table       type    possible_keys             key       key_len ref                           rows  Extra
1   SIMPLE      csu_users   index   user_id                   user_id   5       NULL                          1     Using index
1   SIMPLE      notes       ref     user_id,timestamp,system  user_id   4       REFSYS_DEV.csu_users.user_id  152   Using where

我应用了以下索引:

notes

  • 首要的关键 -id
  • item_id
  • user_id
  • timestamp (注意:这实际上是一个DATETIME. 这个名字只是误导,对不起!)
  • system

csu_users

  • 首要的关键 -id
  • user_id

有什么想法可以加快速度吗?谢谢!

4

2 回答 2

1

csu_users桌子有必要吗?如果关系是 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

即使不是这样,您也可以在聚合和过滤之后进行连接,因为所有条件都 on 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
于 2013-03-20T14:04:38.067 回答
1

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

于 2013-03-20T11:57:55.403 回答