어디서 닫히는 지에 따라 다른 실행 시간을 제공하는 제한이있는 쿼리가 있습니다. 저는 MySQL 5.1을 사용하고 있으며, 가장 큰 테이블 인 "경고"에서 약 1 억 개의 레코드를보고 있습니다. 나는이 실행 계획을 볼 때MySQL 쿼리 실행 계획 (한계가 다를 경우)
, 나는 행복 해요, 내 쿼리는 두 번째 채 걸리지 :
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;
- | 이드 | select_type | 테이블 | 유형 | possible_keys | 열쇠 | key_len | 심판 | 행 | 추가 |
- | 1 | 단순 | 경고 | 색인 | categoryIndex | PRIMARY | 8 | NULL | 40 | |
- | 1 | 단순 | 카테고리 | eq_ref | PRIMARY, severityIndex | PRIMARY | 8 | am.alert.categoryId | 1 | 사용 위치 |
- | 1 | 단순 | 분석기 | eq_ref | PRIMARY | PRIMARY | 8 | am.alert.analyzerId | 1 | |
- | 1 | 단순 | analyzerNode | eq_ref | PRIMARY | PRIMARY | 8 | am.alert.analyzerNodeId | 1 | |
- | 1 | 단순 | sourceNode | eq_ref | PRIMARY | PRIMARY | 8 | am.alert.sourceNodeId | 1 | |
- | 1 | 단순 | targetNode | eq_ref | PRIMARY | PRIMARY | 8 | am.alert.targetNodeId | 1 | |
- | 1 | 단순 | sourceUser | eq_ref | PRIMARY | PRIMARY | 8 | am.alert.sourceUserId | 1 | |
- | 1 | 단순 | targetUser | eq_ref | PRIMARY | PRIMARY | 8 | am.alert.targetUserId | 1 | |
- | 1 | 단순 | 참고 문헌 | eq_ref | PRIMARY | PRIMARY | 8 | am.alert.referenceId | 1 | |
그러나 where 절 (이 경우 열거 형이지만 값이 적절하지 않다고 생각합니다)의 값을 변경하면 극적으로 다른 결과를 얻을 수 있으며 내 쿼리에는 영원히 걸릴 수 있습니다.
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;
- | 이드 | select_type | 테이블 | 유형 | possible_keys | 열쇠 | key_len | 심판 | 행 | 추가 |
- | 1 | 단순 | 카테고리 | 심판 | PRIMARY, severityIndex | severityIndex | 2 | const | 8 | 사용 장소; 임시 사용; filesort 사용 |
- | 1 | 단순 | 경고 | 심판 | categoryIndex | categoryIndex | 8 | am.category.id | 3883428 | |
- | 1 | 단순 | 분석기 | eq_ref | PRIMARY | PRIMARY | 8 | am.alert.analyzerId | 1 | |
- | 1 | 단순 | analyzerNode | eq_ref | PRIMARY | PRIMARY | 8 | am.alert.analyzerNodeId | 1 | |
- | 1 | 단순 | sourceNode | eq_ref | PRIMARY | PRIMARY | 8 | am.alert.sourceNodeId | 1 | |
- | 1 | 단순 | targetNode | eq_ref | PRIMARY | PRIMARY | 8 | am.alert.targetNodeId | 1 | |
- | 1 | 단순 | sourceUser | eq_ref | PRIMARY | PRIMARY | 8 | am.alert.sourceUserId | 1 | |
- | 1 | 단순 | targetUser | eq_ref | PRIMARY | PRIMARY | 8 | 오전.targetUserId | 1 | |
- | 1 | 단순 | 참고 문헌 | eq_ref | PRIMARY | PRIMARY | 8 | am.alert.referenceId | 1 | |
실행의 첫 번째 단계로 제한이 있고 다른 하나는 제한이없는 것에 유의하십시오. 어쨌든 MySQL 쿼리 최적화 프로그램이 이것을 먼저 수행하도록 강제 할 것입니까?
첫 번째 조인을 '내부 조인'으로 변경하면 어떻게됩니까? _Your'WHERE'는 효과적으로 결과를 바꾸지 않으므로 결과를 바꿔서는 안됩니다. _ – Uueerdo
최적화 도구 힌트를 사용할 수 있습니다 : https://dev.mysql.com/doc/refman/5.7/en/optimizer-hints.html . 또 다른 방법은 나쁜 실행 계획을 좋게 만드는 인덱스를 추가하거나 옵티마이 저가 다른 계획을 생성하는 것입니다. – mm759
INNER JOIN은 쿼리 또는 실행 계획의 성능을 변경하지 않았습니다. 옵티 마이저 힌트에 관해서는 솔직히 제 문제에 대한 해결책으로 나를 움켜 쥐었던 것을 보지 못했습니다. 나는 제안에 개방적이다. – Agricola