[英]Optimizing mysql query for better performance to get low execution time
[英]Optimizing this piece of MYSQL Code for better execution time
這段mysql代碼
SELECT id, value, LENGTH(stuffing)
FROM t_limit ORDER BY id LIMIT 150000, 10
可以通過這樣重寫來優化以獲得更好的性能
注意:表上有ID索引
SELECT l.id, value, LENGTH(stuffing)
FROM (
SELECT id
FROM t_limit
ORDER BY
id
LIMIT 150000, 10
) o
JOIN t_limit l
ON l.id = o.id
ORDER BY
l.id
參考:http://explainextended.com/2009/10/23/mysql-order-by-limit-performance-late-row-lookups/
現在如何以類似方式優化這段代碼
SELECT id, value, LENGTH(stuffing)
FROM t_limit where value>100 ORDER BY id LIMIT 150000, 10
提到的帖子中提出的優化背后的基本思想是僅查詢索引頁而不接觸數據頁。 如果您查看未優化查詢的查詢計划:
SELECT id, value, LENGTH(stuffing) AS len
FROM t_limit
ORDER BY
id
LIMIT 150000, 10
這將是:
+----+-------------+---------+------+---------------+------+---------+------+--------+----------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra
+----+-------------+---------+------+---------------+------+---------+------+--------+----------------+
| 1 | SIMPLE | t_limit | ALL | NULL | NULL | NULL | NULL | 200000 | Using filesort |
+----+-------------+---------+------+---------------+------+---------+------+--------+----------------+
因此,這是一個簡單的表格掃描。 通過子查詢優化,我們收到:
+----+-------------+------------+--------+-------------------------------+---------+---------+------+--------+---------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+------------+--------+-------------------------------+---------+---------+------+--------+---------------------------------+
| 1 | PRIMARY | <derived2> | ALL | NULL | NULL | NULL | NULL | 10 | Using temporary; Using filesort |
| 1 | PRIMARY | l | eq_ref | PRIMARY | PRIMARY | 4 | o.id | 1 | |
| 2 | DERIVED | t_limit | index | NULL | PRIMARY | 4 | NULL | 150010 | Using index |
+----+-------------+------------+--------+-------------------------------+---------+---------+------+--------+---------------------------------+
查看顯示最里面的語句使用PRIMARY索引的key
列。 我稍微修改了您的查詢,以便值類型兼容:
SELECT l.id, value, LENGTH(stuffing) AS len
FROM (
SELECT id
FROM t_limit
where value like 'Value 1%'
ORDER BY
id
LIMIT 30000, 10
) o
JOIN t_limit l
ON l.id = o.id
ORDER BY
l.id
您需要考慮where
條件的作用。 如果將其放在外部查詢中,則僅過濾從內部查詢返回的10行-我想這不是您要的。 現在在所示的情況下(inner語句中的where
條件),您將最終進行表掃描,因為沒有索引可以滿足您的查詢:
+----+-------------+------------+--------+---------------+---------+---------+------+--------+--------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+------------+--------+---------------+---------+---------+------+--------+---------------------------------+
| 1 | PRIMARY | <derived2> | ALL | NULL | NULL | NULL | NULL | 10 | Using temporary; Using filesort |
| 1 | PRIMARY | l | eq_ref | PRIMARY | PRIMARY | 4 | o.id | 1 | |
| 2 | DERIVED | t_limit | ALL | NULL | NULL | NULL | NULL | 200000 | Using filesort |
+----+-------------+------------+--------+---------------+---------+---------+------+--------+---------------------------------+
為了從博客文章中介紹的相同優化中獲利,您需要一個附加的非聚集索引,例如。
create index NCIX_t_limit_id_value on t_limit(id, value)
現在,當您運行上述查詢時,該計划將是:
+----+-------------+------------+--------+-------------------------------+-----------------------+---------+------+-------+---------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+------------+--------+-------------------------------+-----------------------+---------+------+-------+---------------------------------+
| 1 | PRIMARY | <derived2> | ALL | NULL | NULL | NULL | NULL | 10 | Using temporary; Using filesort |
| 1 | PRIMARY | l | eq_ref | PRIMARY,NCIX_t_limit_id_value | PRIMARY | 4 | o.id | 1 | |
| 2 | DERIVED | t_limit | index | NULL | NCIX_t_limit_id_value | 66 | NULL | 30010 | Using where; Using index |
+----+-------------+------------+--------+-------------------------------+-----------------------+---------+------+-------+---------------------------------+
同樣,我們只掃描索引頁面。
您可以將查詢編寫為:
SELECT l.id, value, LENGTH(stuffing)
FROM (SELECT id
FROM t_limit
WHERE value > 100
ORDER BY id
LIMIT 150000, 10
) o JOIN
t_limit l
ON l.id = o.id
ORDER BY l.id
但是,這不會提高性能。 MySQL必須讀取數據頁以獲取具有正確值的行。
您還可以使用其他索引:(值),(值,id)和(id,值)。 這些將對性能產生不同的影響。
第一個將使用索引來滿足WHERE
子句,然后基本上忽略索引的“ id”部分。 如果value > 100
具有高度選擇性(例如,少於1%的記錄滿足此條件),這將提高性能。
第二個可能有幫助。 老實說,我不知道MySQL是否將從索引中讀取ID,然后進行排序。 或者,如果它將讀取原始數據。 如果是第一個,這將有所幫助。
第三個可能是最好的選擇。 我認為MySQL將讀取索引以查找匹配的值,然后將索引用於排序和限制。 我的意思是,應該,但是我不是100%肯定引擎會真正做到這一點。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.