我一直在尝试优化我的表格,但仍无法获得所需的结果。
CREATE TABLE IF NOT EXISTS `puzzles` (
`puzzleID` int(7) NOT NULL,
`puzzleMask` varchar(30) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL,
`puzzleScore` int(7) NOT NULL,
`time` int(11) NOT NULL DEFAULT '0',
`hour` int(11) NOT NULL DEFAULT '0',
`ip` varchar(20) CHARACTER SET utf8 COLLATE utf8_unicode_ci DEFAULT NULL,
`Iip` int(11) unsigned NOT NULL DEFAULT '1',
PRIMARY KEY (`puzzleID`, `puzzleMask`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=1;
ID和Mask的组合必须是唯一的,而ID是随机整数,Mask是最大长度为30的数字组合。time是unix时间戳,hour是“time - (time % 3600)”(时间在该行已提交)。ip 是服务器的 IP 地址(大约 20 个服务器),Iip 是 INET_ATON( ip )。
这 20 台服务器向该数据库提交拼图信息。我想显示提交信息的实时统计信息(每秒 5-10 条记录)。
为此,我使用了两个需要尽可能优化的主要查询:
获取总统计
SELECT COUNT(*) AS total, MAX(puzzleScore) AS maxScore, hour FROM puzzles WHERE hour => #startHour# GROUP BY hour
获取服务器相关统计信息
SELECT COUNT(*) AS total, MAX(puzzleScore) AS maxScore, hour FROM puzzles WHERE hour => #startHour# AND Iip = INET_ATON("#IPAddress#") GROUP BY hour
我的问题是,使用什么索引?我现在已经尝试了很多东西,但是随着数据库的快速增加,试验和错误的时间已经结束了……例如,我是否需要一个单独的 puzzleScore 索引,因为我想要最大值?或者我需要将它合并到另一个索引中吗?
此外,将主键(puzzleID 和 puzzleMask)与 INSERT IGNORE INTO... 结合使用是否比使用具有自动增量的 id 并首先执行 SELECT 以查看记录是否存在以及插入更利于性能? ?
谢谢
你试过什么?这两个查询都运行缓慢吗?是否有其他操作已成为问题?由于您有一个实时系统,而不是推测可能导致问题的原因,您可以添加一些分析来确定。
您的第一个查询可以按
( Hour, PuzzleScore )
该顺序由 上的索引回答。你的第二个需要添加Iip
; 因为它应该有很好的基数,所以我把它放在第一位:( Iip, Hour, PuzzleScore )
。检查EXPLAIN
以确认索引是否实际使用;根据行数和基数,可能没有任何好处。由于您正在以
Hour
任何一种方式进行查询,因此我会考虑对该字段进行聚类(当然,结合唯一字段或字段组合以确保唯一性)。警告:我主要在 SQL-Server 工作,我不是 MySQL 方面的专家。