mysql—向列添加索引会提高sql中的select查询(无where)性能吗?

vxbzzdmp  于 2021-08-01  发布在  Java
关注(0)|答案(2)|浏览(299)

我有一个mysql表,它包含20000行和列(user\u id、registered\u timestamp等)。我已经写了下面的查询,以获得每天注册的用户数。执行查询需要很长时间。向registered\u timestamp列添加索引是否会提高执行时间?

select date(registered_timestamp), count(userid) from table group by 1
dvtswwa3

dvtswwa31#

考虑使用此查询获取日期列表和每个日期的注册数。

SELECT date(registered_timestamp) date, COUNT(*) 
   FROM table
  GROUP BY date(registered_timestamp)

然后在 table(registered_timestamp) 会有点帮助,因为这是一个覆盖指数。
例如,如果您调整查询以返回有限范围内的日期。

SELECT date(registered_timestamp) date, COUNT(*) 
   FROM table
  WHERE registered_timestamp >= CURDATE() - INTERVAL 8 DAY
    AND registered_timestamp < CURDATE() 
  GROUP BY date(registered_timestamp)

索引会有帮助(此查询返回昨天结束的一周的结果。)但是,索引对此查询没有帮助。

SELECT date(registered_timestamp) date, COUNT(*) 
   FROM table
  WHERE DATE(registered_timestamp) >= CURDATE() - INTERVAL 8 DAY /* slow! */
  GROUP BY date(registered_timestamp)

因为列上的函数使查询无法合并。
您可能可以使用mysql生成的列来解决这个性能问题。此命令:

ALTER TABLE `table` 
       ADD registered_date DATE 
       GENERATED ALWAYS AS DATE(registered_timestamp)
       STORED;

然后可以在生成的列上添加索引

CREATE INDEX regdate ON `table` ( registered_date );

然后可以在查询中使用生成的(派生的)列,并从该索引中获得大量帮助。

SELECT registered_date, COUNT(*) 
   FROM table
  GROUP BY registered_date;

但是要注意,创建生成的列及其索引需要一段时间。

rvpgvaaj

rvpgvaaj2#

select date(registered_timestamp), count(userid) from table group by 1

将受益于 INDEX(registered_timestamp, userid) 但这只是因为这样的指数是“覆盖”的。查询仍然需要读取索引的每一行,并进行文件排序。
如果 useridPRIMARY KEY ,那么这将给你相同的答案,而不必费心检查每一个 userid 因为存在 NOT NULL .

select date(registered_timestamp), count(*) from table group by 1

以及 INDEX(registered_timestamp) 相当于上述建议(这是因为innodb隐式地添加了pk。)
如果这个查询是常见的,那么您可以构建并维护一个“摘要表”,该表收集当天注册的每晚计数。那么查询将是从较小的表中更快地获取数据。

相关问题