我有一个限制的查询,根据close所在的值提供截然不同的执行时间。我正在使用MySQL 5.1,在我最大的表格中查看大约100,000,000条记录"警报"。
当我看到这个执行计划时,我很高兴,我的查询不到一秒钟:
mysql> EXPLAIN SELECT alert.id, category.severity, category.classification, category.completion, alert.description,
-> alert.detectTime, analyzer.name, analyzer.manufacturer, analyzer.model, analyzer.version,
-> analyzer.class, analyzer.osType, analyzer.osVersion, analyzerNode.hostName,
-> analyzerNode.address, sourceNode.hostName, sourceNode.address, targetNode.hostName,
-> targetNode.address, sourceUser.userName, sourceUser.uid, targetUser.userName, targetUser.uid,
-> alert.filePath, alert.sourceProcessPid, alert.sourceProcessPath, alert.targetProcessPid,
-> alert.targetProcessPath, alert.acknowledgeUserName, alert.acknowledgeTime, reference.url, reference.meaning
-> FROM alerts AS alert
-> LEFT JOIN categories AS category ON category.id = alert.categoryId
-> LEFT JOIN analyzers AS analyzer ON analyzer.id = alert.analyzerId
-> LEFT JOIN nodes AS analyzerNode ON analyzerNode.id = alert.analyzerNodeId
-> LEFT JOIN nodes AS sourceNode ON sourceNode.id = alert.sourceNodeId
-> LEFT JOIN nodes AS targetNode ON targetNode.id = alert.targetNodeId
-> LEFT JOIN users AS sourceUser ON sourceUser.id = alert.sourceUserId
-> LEFT JOIN users AS targetUser ON targetUser.id = alert.targetUserId
-> LEFT JOIN `references` AS reference ON reference.id = alert.referenceId
-> WHERE category.severity = 'info'
-> ORDER BY alert.id DESC
-> LIMIT 40 OFFSET 0;
但是,当我只是更改where子句的值(在这种情况下是枚举,但我不认为相关)时,我可以得到截然不同的结果,我的查询将永远。< / p>
mysql> EXPLAIN SELECT alert.id, category.severity, category.classification, category.completion, alert.description,
-> alert.detectTime, analyzer.name, analyzer.manufacturer, analyzer.model, analyzer.version,
-> analyzer.class, analyzer.osType, analyzer.osVersion, analyzerNode.hostName,
-> analyzerNode.address, sourceNode.hostName, sourceNode.address, targetNode.hostName,
-> targetNode.address, sourceUser.userName, sourceUser.uid, targetUser.userName, targetUser.uid,
-> alert.filePath, alert.sourceProcessPid, alert.sourceProcessPath, alert.targetProcessPid,
-> alert.targetProcessPath, alert.acknowledgeUserName, alert.acknowledgeTime, reference.url, reference.meaning
-> FROM alerts AS alert
-> LEFT JOIN categories AS category ON category.id = alert.categoryId
-> LEFT JOIN analyzers AS analyzer ON analyzer.id = alert.analyzerId
-> LEFT JOIN nodes AS analyzerNode ON analyzerNode.id = alert.analyzerNodeId
-> LEFT JOIN nodes AS sourceNode ON sourceNode.id = alert.sourceNodeId
-> LEFT JOIN nodes AS targetNode ON targetNode.id = alert.targetNodeId
-> LEFT JOIN users AS sourceUser ON sourceUser.id = alert.sourceUserId
-> LEFT JOIN users AS targetUser ON targetUser.id = alert.targetUserId
-> LEFT JOIN `references` AS reference ON reference.id = alert.referenceId
-> WHERE category.severity = 'high'
-> ORDER BY alert.id DESC
-> LIMIT 40 OFFSET 0;
注意一个人有限制作为执行的第一步,另一个没有。无论如何都要强制MySQL查询优化器首先执行限制吗?
答案 0 :(得分:0)
使用ORDER BY和LIMIT时,重要的是订单依据索引。
如果优化程序决定选择另一个索引,则不会应用限制,因为检索结果并扫描更多记录。
在您的情况下,您可能没有“信息”警报更少的“高”,优化程序更喜欢类别表中的严重性索引。
您可以尝试使用FORCE INDEX
强制使用警报表的PK,或尝试忽略类别表的严重性索引。
这个article似乎很有用。