首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

MySQL 查詢優化:ORDER BY 導致 1 萬條數據查詢 14 秒

     編輯:程式設計綜合問答

問題 SQL

SELECT t1.id, t1.order_no, t1.order_status, t1.pay_status, t1.shipping_status,
       t1.pay_method, t1.invoice, t1.remark, t1.seller, t1.buyer, t1.site_id,
       t1.order_time, t1.pay_time, t1.sign_for_time, t1.delivery_time,
       t1.subtotal, t1.freight, t1.invitation, t1.cope, t1.is_comment, t1.pay_discount
FROM zcwl_order t1
LEFT JOIN zcwl_order_shipping_address t2 ON t2.order_id = t1.id
WHERE t1.site_id
ORDER BY t1.order_time DESC;

數據量 ~1 萬條,耗時 14 秒。去掉 ORDER BY 即正常。

優化分析

1. 缺少索引

ORDER BY t1.order_time DESC 需要對結果集排序。若 order_time 無索引,MySQL 必須將滿足條件的所有行讀入內存進行 filesort,極其耗時。

解決:添加聯合索引覆蓋 WHERE 與 ORDER BY:

ALTER TABLE zcwl_order ADD INDEX idx_site_time (site_id, order_time DESC);

此索引使查詢可直接按索引順序讀取,避免 filesort。

2. SELECT * / 過多列

查詢選取 22 個列,增加 I/O 開銷。若不需要所有列,明確列出所需列;或將大文本列(如 remark)移至副表按需關聯。

3. LEFT JOIN 必要性檢查

若 t2 表字段未在 SELECT 或 WHERE 中使用,純屬多餘關聯,可刪除。若需關聯,確保 t2.order_id 有索引。

4. WHERE 條件 t1.site_id 寫法

原 SQL WHERE t1.site_id 等價於 WHERE t1.site_id <> 0(非零即真),可能非預期。應明確值:WHERE t1.site_id = ?。

5. 執行計劃驗證

EXPLAIN SELECT ... ORDER BY t1.order_time DESC;

關注 type(應為 ref/range)、key(用到索引)、Extra(無 Using filesort、Using temporary)。

優化後 SQL 示例

SELECT t1.id, t1.order_no, t1.order_status, t1.order_time, t1.subtotal
FROM zcwl_order t1
WHERE t1.site_id = 1001
ORDER BY t1.order_time DESC
LIMIT 20; -- 分頁必加 LIMIT

索引設計原則

  • 最左前綴:(site_id, order_time) 支持 WHERE site_id=... ORDER BY order_time。
  • 覆蓋索引:若查詢僅需索引列,Extra 顯示 Using index,無需回表。
  • 避免冗餘索引:單列 site_id 索引可被聯合索引替代。

避坑提醒

  • 大表 ORDER BY 無索引 = 全表掃描 + filesort = 災難。
  • 分頁深度大時 LIMIT 100000, 20 仍慢,改用「游標分頁」(WHERE id > last_id ORDER BY id LIMIT 20)。
  • 定期 ANALYZE TABLE 更新統計信息,防止優化器選錯計劃。

加上 (site_id, order_time DESC) 聯合索引並修正 WHERE 條件,通常能將 14 秒降至 < 100ms。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved