【发布时间】:2021-06-13 06:39:42
【问题描述】:
我制作了一个应用程序,在登录和退出另一个应用程序时注册用户。该应用程序基本上将用户 ID、设备、IP 和登录记录为时间戳。
| id ???? | user ???? | device | ip | signed_in | signed_out |
|---|---|---|---|---|---|
| 1 | 38 | ChromeOS | 174.134.24.35 | 2020-05-01 09:32:01 | 2020-05-01 18:32:01 |
| 2 | 39 | ChromeOS | 174.134.24.35 | 2020-05-01 09:32:01 | 2020-05-01 18:32:01 |
我将保存详细信息,只是说这个应用程序的目的是然后汇总用户每个月在另一个应用程序中花费的时间。
获取一个月内所有用户的SQL查询比较简单:
SELECT *
FROM users
WHERE id = 38
AND signed_in >= 2020-05-01 00:00:00
AND signed_out < 2020-06-01 00:00:00
虽然最初没有任何问题,但据报道,生成总和的速度大幅放缓,随着越来越多的人使用网络服务,该总和已经增长。经过一些干预后,由于时间戳的原因,查询速度大大减慢,因为必须进行全面扫描。
可能的解决方案
我还没有找到任何解决这个性能问题的方法,除了一个:为年月组合添加列,索引它们,并将它们与查询一起使用。
| id ???? | user ???? | device | ip | year ???? | month ???? | signed_in | signed_out |
|---|---|---|---|---|---|---|---|
| 1 | 38 | ChromeOS | 174.134.24.35 | 2020 | 5 | 2020-05-01 09:32:01 | 2020-05-01 18:32:01 |
| 2 | 39 | ChromeOS | 174.134.24.35 | 2020 | 5 | 2020-05-01 09:32:01 | 2020-05-01 18:32:01 |
SELECT *
FROM users
WHERE id = 38
AND year = 2020
AND month = 5
这可能是不将解决方案绑定到单个数据库引擎(我正在考虑 MySQL 和 PostgreSQL)的好方法。考虑到数据库越大,数据库扫表的时间越长,这种方法似乎是不可避免的,而索引可以帮助处理每月生成的数千条记录。
除了这个解决方案,我没有想法。
【问题讨论】:
-
您使用原始列创建了什么索引?我的猜测是您将日期时间作为第一列,这意味着您必须阅读所有符合日期范围的索引(包括在
id过滤器上不匹配的索引) -
总和是什么?是您问题中的查询还是其他查询有问题?
标签: mysql sql postgresql performance datetime