적합한 where 조건이 없을 때 order by 이후의 필드를 드라이버로 조회하기 위해 선택하십시오

백그라운드 쿼리 문
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가 이 조건을 사용하도록 강제할 수 있습니다!

좋은 웹페이지 즐겨찾기