mysql - 使用复合索引优化查询,即使用where

标签 mysql performance optimization indexing range

我有下表“残局”如下:

DROP TABLE IF EXISTS `DB`.`endgames`; 
    CREATE TABLE `DB`.`endgames` ( 
    `ID` int(11) NOT NULL AUTO_INCREMENT, 
    `GamePosition` char(64) NOT NULL DEFAULT '0123421055555555CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCBBBBBBBB6789A876', 
    `GameIntroduction` text, 
    `Event` varchar(40) DEFAULT NULL, 
    `Site` varchar(40) DEFAULT NULL, 
    `GameDate` varchar(25) DEFAULT NULL, 
    `Round` varchar(10) DEFAULT NULL, 
    `WhitePlayer` varchar(80) NOT NULL, 
    `BlackPlayer` varchar(80) DEFAULT NULL, 
    `Result` tinyint(3) unsigned DEFAULT NULL, 
    `ECOCode` smallint(6) unsigned DEFAULT NULL, 
    `Annotator` varchar(100) DEFAULT NULL, 
    `EventCountry` varchar(40) DEFAULT NULL, 
    `GameText` text, 
    `WhiteMove` bit(1) DEFAULT b'1', 
    `MoveOffset` smallint(6) DEFAULT '0', 
    `TextComments` int(10) unsigned DEFAULT NULL, 
    `VariationCount` int(10) unsigned DEFAULT NULL, 
    `WhiteQueenCount` tinyint(3) unsigned NOT NULL, 
    `WhiteRookCount` tinyint(3) unsigned NOT NULL, 
    `WhiteBishopCount` tinyint(3) unsigned NOT NULL, 
    `WhiteKnightCount` tinyint(3) unsigned NOT NULL, 
    `WhitePawnCount` tinyint(3) unsigned NOT NULL, 
    `BlackQueenCount` tinyint(3) unsigned NOT NULL, 
    `BlackRookCount` tinyint(3) unsigned NOT NULL, 
    `BlackBishopCount` tinyint(3) unsigned NOT NULL, 
    `BlackKnightCount` tinyint(3) unsigned NOT NULL, 
    `BlackPawnCount` tinyint(3) unsigned NOT NULL, 
    PRIMARY KEY (`ID`), 
    KEY `IX_PieceCounts`  (`WhiteQueenCount`,`WhiteRookCount`,`WhiteBishopCount`,`WhiteKnightCount`,`WhitePawnCount`,`BlackQueenCount`,`BlackRook
    Count`,`BlackBishopCount`,`BlackKnightCount`,`BlackPawnCount`) 
    ) ENGINE=MyISAM AUTO_INCREMENT=58796 DEFAULT CHARSET=latin1; 

可以看出,Count 字段(我搜索的字段)上有一个复合索引。

我正在使用下面的查询:

解释

SELECT * FROM endgames WHERE WhiteQueenCount >=0 AND WhiteRookCount >=3 AND WhiteBishopCount >=0 AND WhiteKnightCount >=0 AND WhitePawnCount >=0 AND BlackQueenCount >=0 AND BlackRookCount >=0 AND BlackBishopCount >=0 AND BlackKnightCount >=0 AND BlackPawnCount >=0 

联盟

SELECT * FROM endgames WHERE WhiteQueenCount >=0 AND WhiteRookCount >=0 AND WhiteBishopCount >=0 AND WhiteKnightCount >=0 AND WhitePawnCount >=0 AND BlackQueenCount >=0 AND BlackRookCount >=3 AND BlackBishopCount >=0 AND BlackKnightCount >=0 AND BlackPawnCount >=0 

该解释的输出如下:

1, 'PRIMARY', '残局', '范围', 'IX_PieceCounts', 'IX_PieceCounts', '10', '', 8421, '使用位置' 2、'UNION'、'残局'、'ALL'、'IX_PieceCounts'、''、''、''、58795、'使用位置' , '并集结果', '', '全部', '', '', '', '', , ''

在实时环境中,对于具有 60,000 行的表,这可能最多需要 3 秒。有什么办法可以优化查询吗?特别是,我注意到在 UNION 之后的第二部分中没有使用 IX_PieceCounts 索引,并且我看到“using where”以及必须检查大量行。

提前致谢, 蒂姆

最佳答案

数据的重叠可能不足以保证第二次使用索引,我猜在你的大多数游戏中,两个玩家都会移动车超过 3 次,所以你得到了最多(但不是全部) )第一个联合查询的结果。

如果您的查询未参数化,或者没有其他内容依赖于它,您可以尝试删除该联合。 还要选择您要查询的字段,而不是星号,这会花费一些时间。两者的选择必须相同。

SELECT 
   games.ID,
   IF(blackRookCount3.ID IS NULL,0,1) AS blackRookIsGreaterThan3,
   IF(whiteRookCount3.ID IS NULL,0,1) AS whiteRookIsGreaterThan3
FROM endgames 

INNER JOIN 
   endgames games
ON endgames.ID = games.ID      
AND WhiteQueenCount >=0
AND WhiteBishopCount >=0 
AND WhiteKnightCount >=0 
AND WhitePawnCount >=0 
AND BlackQueenCount >=0 
AND BlackBishopCount >=0 
AND BlackKnightCount >=0 
AND BlackPawnCount >=0

LEFT JOIN 
   endgames blackRookCount3
ON endgames.ID = blackRookCount3.ID      
AND blackRookCount3.BlackRookCount >=3 

LEFT JOIN
   endgames whiteRookCount3
ON  endgames.ID = whiteRookCount3.ID      
AND whiteRookCount3.WhiteRookCount >=3 

INNER JOIN
   endgames whiteAndBlackRooks
ON games.ID = whiteAndBlackRooks.ID      
AND whiteRookCount3.ID IS NOT NULL 
AND blackRookCount3.ID IS NOT NULL

关于mysql - 使用复合索引优化查询,即使用where,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25697608/

相关文章:

php - 从 php 调用的 python 脚本连接到数据库

mysql - 检查特定 ID 是否存在于另一个表中或不使用 MySQL 连接

mysql - 无法识别的语句类型(靠近 IF)

c++ - 浮点转换和性能

optimization - 欧拉项目 #1 - 套索

android - JSON + PHP + Java - Android登录mysql

performance - ChromeDriver - 网络性能日志记录 : Understanding timing section of Network. 响应已接收

java - 最小化 Java 线程上下文切换开销

mysql 查询在数据库上消耗很长时间,但在其他数据库上运行良好

c++ - 进行小于比较还是小于或等于比较更有效?