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 即正常。
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。
查詢選取 22 個列,增加 I/O 開銷。若不需要所有列,明確列出所需列;或將大文本列(如 remark)移至副表按需關聯。
若 t2 表字段未在 SELECT 或 WHERE 中使用,純屬多餘關聯,可刪除。若需關聯,確保 t2.order_id 有索引。
t1.site_id 寫法原 SQL WHERE t1.site_id 等價於 WHERE t1.site_id <> 0(非零即真),可能非預期。應明確值:WHERE t1.site_id = ?。
EXPLAIN SELECT ... ORDER BY t1.order_time DESC;
關注 type(應為 ref/range)、key(用到索引)、Extra(無 Using filesort、Using temporary)。
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。