首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 數據庫知識 >  >> SQL Server 資料庫 >> 關於SqlServer

反直覺優化案例:加上 DISTINCT 反而大幅提升查詢效能

     編輯:關於SqlServer

現象:DISTINCT 通常是效能殺手,但這次不同

開發測試發現:加上 DISTINCT 查詢 4 分鐘完成,不加跑 10+ 分鐘無結果。DISTINCT 位於最外層,非子查詢。

模擬環境與實測對比

-- 建表與統計資訊收集
CREATE TABLE T1 AS SELECT * FROM DBA_OBJECTS WHERE OWNER='SYS' AND OBJECT_TYPE NOT LIKE '%BODY' AND OBJECT_TYPE NOT LIKE 'Java%';
CREATE TABLE T2 AS SELECT * FROM DBA_SEGMENTS WHERE OWNER='SYS';
CREATE TABLE T3 AS SELECT * FROM DBA_INDEXES WHERE OWNER='SYS';
-- PK、索引、統計資訊皆已建立

無 DISTINCT 執行計畫

SELECT T1.OBJECT_NAME, T1.OBJECT_TYPE, T2.TABLESPACE_NAME
FROM T1, T2
WHERE T1.OBJECT_NAME = T2.SEGMENT_NAME
  AND T1.OBJECT_NAME IN (
    SELECT INDEX_NAME FROM T3 WHERE T3.TABLESPACE_NAME = T2.TABLESPACE_NAME
  );
-- 邏輯讀 93,採用 HASH JOIN (SEMI),成本 12

有 DISTINCT 執行計畫

SELECT DISTINCT T1.OBJECT_NAME, T1.OBJECT_TYPE, T2.TABLESPACE_NAME
FROM T1, T2
WHERE T1.OBJECT_NAME = T2.SEGMENT_NAME
  AND T1.OBJECT_NAME IN (
    SELECT INDEX_NAME FROM T3 WHERE T3.TABLESPACE_NAME = T2.TABLESPACE_NAME
  );
-- 邏輯讀 72,採用 HASH JOIN + SORT (UNIQUE),成本 16

根因分析

  • 無 DISTINCT:優化器選擇 HASH JOIN (SEMI) 處理 IN 子查詢,代價較高
  • 有 DISTINCT:優化器預知最終需 SORT UNIQUE,決定改用一般 HASH JOIN 連接,雖增加排序但整體邏輯讀降低
  • 關鍵條件:連接表大、最終結果集小、SELECT 欄位少 → 排序代價 < SEMI JOIN 代價

啟示與警示

  1. 優化無絕對真理,幾乎任何情況都可能發生,切勿被「死規則」綁架
  2. 嚴格意義上,加/不加 DISTINCT 是兩個不同語義的 SQL,本例等價僅因表結構/約束/資料共同限制
  3. 換個環境結果可能天差地遠,切勿將此視為通用優化手法

結語

保持開放心態,以執行計畫與實測為準,才是效能調校的正道。

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