我有一个名为 DATA_TIMESLOTS 的表,其中包含近 150 万行。 该表是这样制作的:
+-------+---------------+-----------+
| ID | SRV_TIMESTAMP | DEVICE_ID |
+-------+---------------+-----------+
| 134322| 1414583866 | A1323 |
| 134323| 1414583832 | B1423 |
| 134324| 1414583876 | A1323 |
| 134325| 1414583883 | B1423 |
| 134326| 1414583896 | A1323 |
| 134327| 1414583964 | C1524 |
| 134328| 1414581065 | A1323 |
| .... | ........ | ..... |
+-------+---------------+-----------+
ID 是增量 PK,SRV_TIMESTAMP 和DEVICE_ID 形成集群主键(因为不同的 device_id 可能具有相同的 srv_timestamp) 另一个名为 DATA_RAW 的表也包含近 150 万行。该表是这样制作的:
+--------------+---------+---------+---------+---------+
| TIMESLOT_ID | POWER#1 | POWER#2 | POWER#3 | POWER#4 |
+--------------+---------+---------+---------+---------+
| 134322| 342532 | 354365 | 643654 | 77687 |
| 134323| 439642 | 269436 | 363466 | 16436 |
| 134324| 436252 | 326436 | 643645 | 31616 |
| 134325| 564326 | 867867 | 176471 | 16466 |
| 134326| 148585 | 643633 | 754277 | 43643 |
| 134327| 345298 | 754765 | 626364 | 32632 |
| 134328| 324898 | 532575 | 634366 | 65436 |
| .... | .. | .. | .. | .. |
+--------------+---------+---------+---------+---------+
显然TIMESLOT_ID是该表的PK。 正如您所看到的,TIMESLOT_ID 是第一个表的外键。 现在我需要获取每天的统计数据如下:
SELECT
T.DEVICE_ID AS DEVICE_ID,
DAY(T.SRV_TIMESTAMP) AS SRV_DAY,
MONTH(T.SRV_TIMESTAMP) AS SRV_MONTH,
YEAR(T.SRV_TIMESTAMP) AS SRV_YEAR,
SUM(D.POWER#1) AS DAY_POWER#1,
SUM(D.POWER#2) AS DAY_POWER#2,
SUM(D.POWER#3) AS DAY_POWER#3,
SUM(D.POWER#4) AS DAY_POWER#4
FROM DATA_RAW AS D
INNER JOIN DATA_TIMESLOTS AS T ON T.ID=D.TIMESLOT_ID
GROUP BY
T.DEVICE_ID,
YEAR(T.SRV_TIMESTAMP),
MONTH(T.SRV_TIMESTAMP),
DAY(T.SRV_TIMESTAMP)
该查询工作正常,但速度非常慢(在 64 位 4 CPU/4GB 计算机上运行 1,5M 条记录大约需要 60 秒)。我怀疑,尽管我在 DATA_TIMESLOTS 表中的 DEVICE_ID、SRV_TIMESTAMP 字段上放置了索引,但由于 >DAY()、MONTH()、YEAR() 函数。所以我尝试改用DATE()函数,但结果是一样的。所以问题是:我是否必须在 DATA_TIMESLOT 表中添加额外的日、月、年字段,在它们上放置适当的索引并浪费一些空间以提高性能,还是有另一种方法在不浪费空间的情况下获得这个结果?
我已经在 My SQLSERVER Express 2005 (Microsoft) 上进行了一些测试,我不得不承认上述问题已完全解决。已确认,在对键或索引应用函数后,MySQL 无法保留键或索引。恕我直言,这是一个相当严重的限制。 解决方案似乎是: 1) 添加 3 个附加字段,分别为日、月、年 2)索引这些字段 3)对这些字段进行分组 另一方面,我正在认真考虑删除时间戳字段的可能性,因为此后就完全没有用了。我学到的教训是,在 MySQL 中,时间戳类型永远不应该用作键或索引,因为当您对其应用函数(例如日、月、小时、年等)时,索引将失效...
最佳答案
您的索引和解释是什么样的?考虑将 Y/M/D 分组合并到 TO_DAYS 调用中,您将在同一列上调用三个函数。
关于MYSQL 按性能分组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26630311/