[英]Improving performance when querying tables by datetime
我制作了一個應用程序,用於在登錄和退出另一個應用程序時注冊用戶。 該應用程序基本上記錄了用戶 ID、設備、IP,並作為時間戳登錄。
ID | 用戶 | 設備 | ip | 登錄 | 退出 |
---|---|---|---|---|---|
1 | 38 | 鉻操作系統 | 174.134.24.35 | 2020-05-01 09:32:01 | 2020-05-01 18:32:01 |
2 | 39 | 鉻操作系統 | 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
雖然最初沒有任何問題,但據報道,生成總和的速度大幅放緩,隨着越來越多的人使用 web 服務,該總和已經增長。 經過一些干預后,由於時間戳的原因,查詢速度大大減慢,因為必須進行全面掃描。
我還沒有找到任何解決這個性能問題的方法,除了一個:為年月組合添加列,索引它們,並將它們與查詢一起使用。
ID | 用戶 | 設備 | ip | 年 | 月 | 登錄 | 退出 |
---|---|---|---|---|---|---|---|
1 | 38 | 鉻操作系統 | 174.134.24.35 | 2020 | 5 | 2020-05-01 09:32:01 | 2020-05-01 18:32:01 |
2 | 39 | 鉻操作系統 | 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)。 考慮到它獲得的數據庫越大,數據庫掃描表的時間越長,這種方法似乎是不可避免的,而索引可以幫助處理每月生成的數千條記錄。
除了這個解決方案,我沒有想法。
您的“可能的解決方案”將與
INDEX(id, year, month)
以任何順序排列列。 如果您有ID...AUTO_INCREMENT
和PRIMARY KEY(id)
那么更好的解決方案是
PRIMARY KEY(id, year, month)
(這本身就失去了對ID
的唯一性檢查;但這可能並不重要。它會加快您的查詢速度。)
缺點是查詢僅適用於一個月的測試,而不是一周等。
我很困惑。 什么是id
? 該表名為users
,但您同時擁有id
和user
列。 也許表應該被稱為logins
,查詢應該有WHERE user=39 AND...
?? 如果是這樣,我將需要重新考慮我的答案。
此外,您說“用戶 ID”但顯示兩列?
我假設您的查詢最多選擇表中 1% 的行。 這是索引有效所必需的。
然后,我將您的查詢稍微改寫為:
SELECT * FROM users
WHERE id = 38
AND signed_in between '2020-05-01 00:00:00' AND '2020-05-30 23:59:59'
AND signed_out < '2020-05-30 23:59:59'
以這種方式改寫的查詢可以使用索引通過id
和signed_in
有效地訪問行:
create index ix1 on users (id, signed_in, signed_out);
請注意,我還在索引中添加了signed_out
,以用於覆蓋范圍和避免對索引的雙重打擊。
另外,我假設列signed_in
和signed_out
不是VARCHAR
而是DATETIME
。
首先,我將查詢編寫為:
SELECT *
FROM users u
WHERE id = 38 AND
signed_in >= '2020-05-01' AND
signed_out < '2020-05-31'
雖然我猜你真的想要:
SELECT *
FROM users u
WHERE id = 38 AND
signed_in >= '2020-05-01' AND
signed_out < '2020-06-01'
這包含僅在 5 月份登錄的用戶。 我希望users(id, signed_in)
或users(id, signed_out)
的索引就足夠了。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.