적합한 where 조건이 없을 때 order by 이후의 필드를 드라이버로 조회하기 위해 선택하십시오
11516 단어 mysqlbyorderby 최적화정렬 sql 최적화
SELECT o.orders_id, s.orders_status_name, ot.text ,af.affiliate_id
FROM orders o
LEFT JOIN orders_total ot ON (o.orders_id = ot.orders_id)
LEFT JOIN affiliate_sales AS afs ON afs.affiliate_orders_id = o.orders_id
LEFT JOIN affiliate_affiliate AS af ON af.affiliate_id = afs.affiliate_id
LEFT JOIN orders_status s ON o.orders_status = s.orders_status_id
WHERE s.language_id = '1'
AND (ot.class = 'ot_total' OR ot.orders_total_id IS NULL)
ORDER BY o.orders_id DESC LIMIT 0, 20
어떤 백엔드 조회가 매우 느리다는 고객의 반응이 있습니다. 프로그램을 통해 대응하는 sql를 찾습니다. 위와 같습니다!
explain 검색
+----+-------------+-------+--------+----------------------------+----------------------------+---------+-----------------------------+-------+----------------------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+--------+----------------------------+----------------------------+---------+-----------------------------+-------+----------------------------------------------+
| 1 | SIMPLE | s | ALL | PRIMARY | NULL | NULL | NULL | 21 | Using where; Using temporary; Using filesort |
| 1 | SIMPLE | o | ref | orders_status | orders_status | 4 | banggood.s.orders_status_id | 31747 | |
| 1 | SIMPLE | ot | ref | idx_orders_total_orders_id | idx_orders_total_orders_id | 4 | banggood.o.orders_id | 19 | Using where |
| 1 | SIMPLE | afs | ref | PRIMARY | PRIMARY | 4 | banggood.o.orders_id | 11 | Using index |
| 1 | SIMPLE | af | eq_ref | PRIMARY | PRIMARY | 4 | banggood.afs.affiliate_id | 1 | Using index |
+----+-------------+-------+--------+----------------------------+----------------------------+---------+-----------------------------+-------+----------------------------------------------+
s표는 드라이버로 사용되고 s표는 전체 표를 스캔하며 o표는status 형식의 선택성이 매우 낮은 필드를 인덱스로 사용합니다.
초보적으로 보면 색인 사용이 부적절하다는 것을 알 수 있다!
우리는 이 문장where 조건 중 적합한 구동 조건이 없다는 것을 알 수 있다.그러나order by에서order by o.orders 발견id(orders id는 orders 테이블의 주 키)우리는 이 특성을 이용할 수 있다!
orders표를 강제로 사용하는ordersid 인덱스로 구동!
다음과 같이 변경합니다.
EXPLAIN SELECT o.orders_id, s.orders_status_name, ot.text ,af.affiliate_id
FROM orders o FORCE INDEX(PRIMARY)
LEFT JOIN orders_total ot ON (o.orders_id = ot.orders_id)
LEFT JOIN affiliate_sales AS afs ON afs.affiliate_orders_id = o.orders_id
LEFT JOIN affiliate_affiliate AS af ON af.affiliate_id = afs.affiliate_id
LEFT JOIN orders_status s ON o.orders_status = s.orders_status_id
WHERE s.language_id = '1'
AND (ot.class = 'ot_total' OR ot.orders_total_id IS NULL)
ORDER BY o.orders_id DESC LIMIT 0, 20;
+----+-------------+-------+--------+----------------------------+----------------------------+---------+--------------------------------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+--------+----------------------------+----------------------------+---------+--------------------------------+------+-------------+
| 1 | SIMPLE | o | index | NULL | PRIMARY | 4 | NULL | 1 | |
| 1 | SIMPLE | s | eq_ref | PRIMARY | PRIMARY | 8 | banggood.o.orders_status,const | 1 | Using where |
| 1 | SIMPLE | ot | ref | idx_orders_total_orders_id | idx_orders_total_orders_id | 4 | banggood.o.orders_id | 19 | Using where |
| 1 | SIMPLE | afs | ref | PRIMARY | PRIMARY | 4 | banggood.o.orders_id | 11 | Using index |
| 1 | SIMPLE | af | eq_ref | PRIMARY | PRIMARY | 4 | banggood.afs.affiliate_id | 1 | Using index |
+----+-------------+-------+--------+----------------------------+----------------------------+---------+--------------------------------+------+-------------+
두 번의 프로필링 비교하기;
전자:
+--------------------------------+------------+-----------+------------+--------------+---------------+
| Status | Duration | CPU_user | CPU_system | Block_ops_in | Block_ops_out |
+--------------------------------+------------+-----------+------------+--------------+---------------+
| starting | 0.000027 | 0.000000 | 0.000000 | 0 | 0 |
| Waiting for query cache lock | 0.000006 | 0.000000 | 0.000000 | 0 | 0 |
| checking query cache for query | 0.000130 | 0.000000 | 0.000000 | 0 | 0 |
| checking permissions | 0.000007 | 0.000000 | 0.000000 | 0 | 0 |
| checking permissions | 0.000003 | 0.000000 | 0.000000 | 0 | 0 |
| checking permissions | 0.000003 | 0.000000 | 0.000000 | 0 | 0 |
| checking permissions | 0.000003 | 0.000000 | 0.000000 | 0 | 0 |
| checking permissions | 0.000007 | 0.000000 | 0.000000 | 0 | 0 |
| Opening tables | 0.000130 | 0.000000 | 0.000000 | 0 | 8 |
| System lock | 0.000017 | 0.000000 | 0.000000 | 0 | 0 |
| Waiting for query cache lock | 0.000033 | 0.000000 | 0.000000 | 0 | 0 |
| init | 0.000057 | 0.000000 | 0.000000 | 0 | 0 |
| optimizing | 0.000026 | 0.000000 | 0.000000 | 0 | 0 |
| statistics | 0.000041 | 0.000000 | 0.000000 | 0 | 0 |
| preparing | 0.000031 | 0.000000 | 0.000000 | 0 | 0 |
| Creating tmp table | 0.000111 | 0.001000 | 0.000000 | 0 | 0 |
| executing | 0.000007 | 0.000000 | 0.000000 | 0 | 0 |
| Copying to tmp table | 3.541123 | 0.968852 | 2.357642 | 75800 | 0 |
| converting HEAP to MyISAM | 0.239566 | 0.038994 | 0.198969 | 0 | 262152 |
| Copying to tmp table on disk | 174.185144 | 13.864893 | 35.361625 | 2135152 | 2500280 |
| Sorting result | 20.923419 | 0.127980 | 3.017541 | 2770408 | 27536 |
| Sending data | 0.045078 | 0.000000 | 0.002999 | 1208 | 0 |
| end | 0.000018 | 0.000000 | 0.000000 | 0 | 0 |
| removing tmp table | 0.881884 | 0.018997 | 0.160976 | 760 | 8 |
| end | 0.003960 | 0.000000 | 0.002000 | 448 | 0 |
| query end | 0.000012 | 0.000000 | 0.000000 | 0 | 0 |
| closing tables | 0.031745 | 0.000000 | 0.000999 | 936 | 0 |
| freeing items | 0.015499 | 0.000000 | 0.003000 | 808 | 0 |
| Waiting for query cache lock | 0.000017 | 0.000000 | 0.000000 | 0 | 0 |
| freeing items | 0.000791 | 0.000000 | 0.000000 | 0 | 0 |
| Waiting for query cache lock | 0.000009 | 0.000000 | 0.000000 | 0 | 0 |
| freeing items | 0.000003 | 0.000000 | 0.000000 | 0 | 0 |
| storing result in query cache | 0.000009 | 0.000000 | 0.000000 | 0 | 0 |
| logging slow query | 0.000003 | 0.000000 | 0.000000 | 0 | 0 |
| logging slow query | 0.000010 | 0.000000 | 0.000000 | 0 | 0 |
| cleaning up | 0.000007 | 0.000000 | 0.000000 | 0 | 0 |
+--------------------------------+------------+-----------+------------+--------------+---------------+
각종 cpu,io 손실, 참혹하기 그지없습니다!이 중 가장 큰 소모는 Copying to tmp table on disk입니다.
최적화된 프로필링
+----------------------+----------+----------+------------+--------------+---------------+
| Status | Duration | CPU_user | CPU_system | Block_ops_in | Block_ops_out |
+----------------------+----------+----------+------------+--------------+---------------+
| starting | 0.000139 | 0.000000 | 0.000000 | 0 | 0 |
| checking permissions | 0.000008 | 0.000000 | 0.000000 | 0 | 0 |
| checking permissions | 0.000003 | 0.000000 | 0.000000 | 0 | 0 |
| checking permissions | 0.000003 | 0.000000 | 0.000000 | 0 | 0 |
| checking permissions | 0.000003 | 0.000000 | 0.000000 | 0 | 0 |
| checking permissions | 0.000007 | 0.000000 | 0.000000 | 0 | 0 |
| Opening tables | 0.000125 | 0.000000 | 0.000000 | 0 | 8 |
| System lock | 0.000018 | 0.000000 | 0.000000 | 0 | 0 |
| init | 0.000057 | 0.000000 | 0.000000 | 0 | 0 |
| optimizing | 0.000026 | 0.000000 | 0.000000 | 0 | 0 |
| statistics | 0.000043 | 0.000000 | 0.000000 | 0 | 0 |
| preparing | 0.000030 | 0.000000 | 0.000000 | 0 | 0 |
| executing | 0.000005 | 0.000000 | 0.000000 | 0 | 0 |
| Sorting result | 0.000006 | 0.000000 | 0.000000 | 0 | 0 |
| Sending data | 0.000573 | 0.000000 | 0.000000 | 0 | 0 |
| end | 0.000008 | 0.000000 | 0.000000 | 0 | 0 |
| query end | 0.000004 | 0.000000 | 0.000000 | 0 | 0 |
| closing tables | 0.000014 | 0.000000 | 0.000000 | 0 | 0 |
| freeing items | 0.000062 | 0.000000 | 0.000000 | 0 | 0 |
| logging slow query | 0.000005 | 0.000000 | 0.000000 | 0 | 0 |
| cleaning up | 0.000007 | 0.000000 | 0.000000 | 0 | 0 |
+----------------------+----------+----------+------------+--------------+---------------+
전자에 비해 후자의 트럼펫은 무시해도 된다!
전후 양자 집행 시간의 비율은 196s대 0.01s!
요약:
만약where에서 데이터를 선별할 적당한 조건이 없을 때order by에 비교적 좋은 조건이 있는 것을 보았다면 우리는 첫 번째로order by의 조건으로 조회를 구동할 것을 생각해야 한다!
그러나 mysql 최적화기는 이 조건을 사용하지 않았습니다.force index가 이 조건을 사용하도록 강제할 수 있습니다!
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
MySQL에서 JSON 인덱싱 - aarondfrancis사람들은 종종 MySQL로 JSON을 인덱싱할 수 없다고 말하지만 완전히 정확하지는 않습니다. MySQL로 JSON 열을 인덱싱하는 것은 완전히 가능합니다! 사람들은 종종 MySQL로 JSON을 인덱싱할 수 없다고 ...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.