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

SQL Server 效能調校實戰:索引、聯結與 WHERE 條件優化全解析

     編輯:關於SqlServer

許多開發者專注於 SQL 邏輯正確性,卻忽略不同寫法在大數據量下的效能落差。本文從索引設計、聯結條件、WHERE 子句三大面向,結合實測案例,示範如何讓查詢速度提升數十倍。

測試環境基準

  • 主機:HP LH II / 330 MHz / 128 MB RAM
  • OS:OpenServer 5.0.4 / Sybase 11.0.3(原理同適用於 SQL Server)
  • 測試表 record:62 萬筆;card 7,896 筆;account 19 萬筆
  • 執行時間 < 1 秒者標註為 (< 1秒)

一、不合理的索引設計

案例:單欄非叢集 vs 叢集 vs 組合索引

索引類型範圍查詢GROUP BY多條件查詢
date 非叢集25 秒55 秒27 秒
date 叢集14 秒28 秒14 秒
(place, date, amount) 組合26 秒27 秒< 1 秒
(date, place, amount) 組合< 1 秒11 秒< 1 秒

核心結論

  1. 大量重複值 + 範圍查詢 + ORDER BY/GROUP BY → 考慮叢集索引,資料實體順序與索引一致,避免全表掃描。
  2. 多欄位頻繁同時存取 → 組合索引,前導欄位必須是最常用的篩選欄位(本例為 date)。
  3. 索引覆蓋:查詢所需欄位全包含在索引鍵中,可直接從索引葉層取回資料,無需回表,效能最優。

二、不充份的聯結條件

案例:兩表聯結,補全條件後 I/O 從 59 萬降至 3.3 萬

-- 原始:僅用 card_no 聯結,I/O ≈ 595,907
SELECT SUM(a.amount) FROM account a, card b WHERE a.card_no = b.card_no

-- 優化:補上 account_no,優化器改選 card 為外層表,I/O ≈ 33,528
SELECT SUM(a.amount) FROM account a, card b 
WHERE a.card_no = b.card_no AND a.account_no = b.account_no

原理:優化器根據聯結條件估算「外層表匹配行數 × 內層表單次查找頁數」,乘積最小者為最佳計畫。補全條件可讓優化器選擇更小的驅動表。

三、不可優化的 WHERE 子句

1. 欄位運算導致索引失效

原寫法 (全表掃描)改寫後 (索引搜尋)
substring(card_no,1,4)='5378' (13 秒)card_no LIKE '5378%' (< 1 秒)
amount/30 < 1000 (11 秒)amount < 30000 (< 1 秒)
convert(char(10),date,112)='19991201' (10 秒)date = '1999/12/01' (< 1 秒)

規則:將運算移至等號右側,保持左側欄位「乾淨」,使優化器能使用索引。

2. IN / OR 觸發工作表策略

-- 慢:IN 轉為 OR,優化器用工作表去重,未用索引 (23 秒 → 62 萬筆時 220 秒)
SELECT COUNT(*) FROM stuff WHERE id_no IN ('0','1')

-- 快:拆分為兩條 UNION ALL,各自用索引 (3~4 秒)
SELECT COUNT(*) FROM stuff WHERE id_no='0'
UNION ALL
SELECT COUNT(*) FROM stuff WHERE id_no='1'

或封裝為預存程序,避免重複編譯與網路往返。

總結

SQL 優化的本質:在結果正確前提下,寫出優化器能識別的語句,充分利用索引,減少 I/O,避免表掃描。應用層優化只是冰山一角,深層還涉及資源配置、網路、OS 調校。

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