我一直在开发一个应用程序,它显示了系统中存在问题的顶级设备。为此,我创建了一个表格:
--------------------- ---------------------
- equipments_201404 - - equipments_201405 -
--------------------- ---------------------
- id - - id -
- equipName - - equipName -
- dateTime - - dateTime -
- ... - - ... -
--------------------- ---------------------
这种分离必须与必须存储的数据量有关。因为那,我想知道是否有办法在查询中或通过PHP获得前十名设备。
答案 0 :(得分:1)
如果您的问题报告少于大约十万个(每月equipments_*
个表中的条目,而不是按月将记录拆分为单独的表,或者将表分开,那绝对是一个坏主意.MySQL确实如此。很好地处理包含数十万行的表。很好。认真。
世界上成千上万的成功应用程序在适当大小的MySQL服务器上处理这种大小的数据集。
另一方面,采用分区的系统需要不断维护。
如果您的体验恰恰相反,那是因为您还没有弄清楚如何正确使用索引和查询。我们无法从您的问题中了解您在日常生产中运行的查询类型,因此无法向您提供有关索引的明确建议。话虽这么说,我想在(dateTime,id)
上放一个索引是有意义的。
如果你有一张桌子,而不是我建议的每月一张桌子,你可以这样做,让你的十大设备失败。
SELECT equipName
FROM equipments
GROUP BY equipName
ORDER BY COUNT(*) DESC
LIMIT 10
如果您想要在当前时间结束的6个月期间排名前十,那么您可以使用此查询。
SELECT equipName
FROM equipments
WHERE dateTime >= NOW() - INTERVAL 6 MONTH
GROUP BY equipName
ORDER BY COUNT(*) DESC
LIMIT 10
即使对于包含数十万行跨越数十年的数据集,(dateTime, equipName)
上的复合索引也会使此查询非常有效。
实际上,您已将数据拆分为月表。以下是您如何处理这些问题的方法。首先:使用一系列UNION ALL
操作来创建包含所有数据的虚拟表。如果您的所有月度表都以相同的顺序具有相同的列,那么如果有点无聊则非常容易。
SELECT * FROM equipments_201404 UNION ALL
SELECT * FROM equipments_201403 UNION ALL
SELECT * FROM equipments_201402 UNION ALL
SELECT * FROM equipments_201401 UNION ALL
SELECT * FROM equipments_201312 UNION ALL
SELECT * FROM equipments_201311 UNION ALL
SELECT * FROM equipments_201310 UNION ALL
SELECT * FROM equipments_201309 UNION ALL
SELECT * FROM equipments_201308 UNION ALL
SELECT * FROM equipments_201307 UNION ALL
SELECT * FROM equipments_201306 UNION ALL
SELECT * FROM equipments_201305 UNION ALL
SELECT * FROM equipments_201304 /* etc etc you get the idea */
如果您发出此查询,您将获得所有记录,就好像它们在一个表中一样。然后,您可以将其用作上面显示的查询中的子查询,如下所示。
SELECT equipName
FROM (
SELECT * FROM equipments_201404 UNION ALL
SELECT * FROM equipments_201403 UNION ALL
SELECT * FROM equipments_201402 UNION ALL
SELECT * FROM equipments_201401 UNION ALL
SELECT * FROM equipments_201312 UNION ALL
SELECT * FROM equipments_201311 UNION ALL
SELECT * FROM equipments_201310 UNION ALL
SELECT * FROM equipments_201309 UNION ALL
SELECT * FROM equipments_201308 UNION ALL
SELECT * FROM equipments_201307 UNION ALL
SELECT * FROM equipments_201306 UNION ALL
SELECT * FROM equipments_201305 UNION ALL
SELECT * FROM equipments_201304 /* etc etc you get the idea */
) AS equipments
WHERE dateTime >= NOW() - INTERVAL 6 MONTH
GROUP BY equipName
ORDER BY COUNT(*) DESC
LIMIT 10
这使您可以假设您的主要摘要查询认为它有一组要处理的统一数据。当然,索引在这里没有多大帮助。
显然,我在六个月的查询中包含了太多的月度表。你可以解决这个问题。但是你每个月都需要修理它。