大部分的 relational DBMS 有自動query最佳化的功能,但這不代表使用者可以完全不處理query的最佳化,因為自動最佳化能做到的是一般情況而非特定問題。另外需要注意的事是,即便是相同廠商的DBMS,不同版本的最佳化的效果可能不一樣。針對Select Statement,可以做的最佳化有以下幾種:
1. Index Selectivity
在DBMS 的 Indexes Optimization中,簡單介紹了Index以及不同種類的Index和特性。Index 被使用情境有以下幾種:
- indexed column 出現在 where 或 having 語句
- indexed column 出現在 group by 或 order by 語句
- indexed column 使用於 MIN 或 MAX 函數
- indexed column 的 data sparsity (異質程度) 高
當要select特定資料列,且資料列總數不高,DBMS可能會選擇使用Indexes。Index selectivity 是DBMS使用index的可能性,我們會希望創造出Selectivity高的Indexes。一般選擇及創造index有以下通用準則:
- 為被 where, having, group by, order by 的屬性(Column)創造index。 比如欄位 A 為 index,where A = 10 可以使用index加速查找。
- 不要在小 table 或 low sparsity table 使用index, 因為會有過多的 index operation 增加成本。
- 宣告 primary key (PK) 以及 foreign key (FK) 使得 join operation 可以使用 index (宣告PK會自動創造index,而FK通常需要自行創建)。
- 若 pk,fk 以外的欄位常用來join,也為此創造index。
另外關於Index還有須注意的有:
Multicolumn Index
可以將多欄位甚至常數組合成 Multicolumn Index,比如有A, B, C欄位,將 (A,B,C) 或 (A,‘1’) 做為 index,當創造 Multicolumn Index 時,欄位的順序是重要的。使用Index時,會從Multicolumn Index的開頭欄位開始,若有出現在where, having等之中就會使用,並依序看下一個欄位。因此當出現在where的欄位是 A,B,C 或 A,B 或 A時 (在where中的順序沒關係),會使用index,但如果是 B,C 或 C 時等情況,就不會使用index。
Null Value
一些DBMS,尤其B-tree結構,單欄位 index 不會包含null value,如果想要讓有null value 的欄位也能在查找is null享有index的好處,可以使用bitmap index 或是 使用 Multicolumn Index (至少包含一個欄位有 NOT NULL 的 constraint 或是技巧性用 ( HAS_NULL_COLUMN, ‘1’ ) 等 )。
Functoin-based Index
一般如果欄位COLUMN_A為index,假設A也為數值型態,當 where 使用上 where some_column_also_index = COLUMN_A*10 ,此時不會使用COLUMN_A的index。
有些支持Functoin-based Index的DBMS可以創造一些像是 COLUMN_A+COLUMN_B 或 YEAR(COLUMN_C),這類基於sql function或一些表達式的index。
不要創造過多的 Index
Index 雖然幫助加速select,但在insert, update, delete操作時會修改index,因此愈多index,在這些操作上的成本愈大。
2. Conditional Expressions
條件表達式一般出現在where 或 having 語句,這些operator如 >, =, like, < 等。
在使用條件表達式時,有些影響效率的特性可以讓我們思考資料庫要怎麼樣設計,如:
- 盡量在條件直接使用欄位比較,避免使用函數或額外計算在欄位上。如 COLUMN_A > COLUMN_B * 10 或 YEAR(EVENT_TIME) = 2000 等,因為會為此消耗資源做計算。可以一開始為此存新的欄位。
- 數值型態的比較比文字、時間、NULL型態快。
- 等式比較比不等式比較來得快。不等式相關的operator包含 >, >=, <, <=, <> ,like是最慢的。所以當有很多條件判斷時,把等式條件放在不等式條件前面為佳。
- 使用 AND 時,把最可能不會成立的條件放前面。
- 使用 OR 時,把最可能成立的條件放在前面。
- 盡量不使用 NOT operator。