標籤

顯示具有 資料庫效能調整 標籤的文章。 顯示所有文章
顯示具有 資料庫效能調整 標籤的文章。 顯示所有文章

2013年9月21日 星期六

寫出更快的SQL

如果在SELECT語句前放上關鍵字EXPLAINMySQL將解釋它如何處理SELECT,提供有關表如何聯接和聯接的次序。借助於EXPLAIN,可以知道什麼時候必須為表加入索引以得到一個使用索引來尋找記錄的更快的SELECT

1EXPLAIN tbl_name

EXPLAIN tbl_nameDESCRIBE tbl_nameSHOW COLUMNS FROM tbl_name的一個同義詞。

2EXPLAIN [EXTENDED] SELECT select_options

如果在SELECT語句前放上關鍵字EXPLAINMySQL將解釋它如何處理SELECT,提供有關表如何聯接和聯接的次序。

借助於EXPLAIN,可以知道什麼時候必須為表加入索引以得到一個使用索引來尋找記錄的更快的SELECT

還可以知道優化器是否以一個最佳次序聯接表。為了強制優化器讓一個SELECT語句按照表命名順序的聯接次序,語句應以STRAIGHT_JOIN而不只是SELECT開頭。

EXPLAIN為用於SELECT語句中的每個表返回一行資訊。表以它們在處理查詢過程中將被MySQL讀入的順序被列出。MySQL用一遍掃描多次聯接(single-sweep multi-join)的方式解決所有聯接。這意味著MySQL從第一個表中讀一行,然後找到在第二個表中的一個匹配行,然後在第3個表中等等。當所有的表處理完後,它輸出選中的列並且返回表清單直到找到一個有更多的匹配行的表。從該表讀入下一行並繼續處理下一個表。

當使用EXTENDED關鍵字時,EXPLAIN產生附加資訊,可以用SHOW WARNINGS流覽。該資訊顯示優化器限定SELECT語句中的表和列名,重寫並且執行優化規則後SELECT語句是什麼樣子,並且還可能包括優化過程的其他注解。

EXPLAIN的每個輸出行提供一個表的相關資訊,並且每個行包括下面的列:

idSELECT識別符。這是SELECT的查詢序列號。

select_typeSELECT類型。

SIMPLE 簡單SELECT(不使用UNION或子查詢)
PRIMARY 最外面的SELECT
UNIONUNION中的第二個或後面的SELECT語句
DEPENDENT UNIONUNION中的第二個或後面的SELECT語句,取決於外面的查詢
UNION RESULTUNION的結果
SUBQUERY:子查詢中的第一個SELECT
DEPENDENT SUBQUERY:子查詢中的第一個SELECT,取決於外面的查詢
DERIVED:導出表的SELECT(FROM子句的子查詢)

table:表名

type:聯接類型

system:表僅有一行(=系統表)。這是const聯接類型的一個特例。

const:表最多有一個匹配行,它將在查詢開始時被讀取。因為僅有一行,在這行的列值可被優化器剩餘部分認為是常數。const用於用常數值比較PRIMARY KEYUNIQUE索引的所有部分時。

eq_ref:對於每個來自於前面的表的行組合,從該表中讀取一行。這可能是最好的聯接類型,除了const類型。它用在一個索引的所有部分被聯接使用並且索引是UNIQUEPRIMARY KEYeq_ref可以用於使用= 操作符比較的帶索引的列。比較值可以為常量或一個使用在該表前面所讀取的表的列的運算式。

ref:對於每個來自於前面的表的行組合,所有有匹配索引值的行將從這張表中讀取。如果聯接只使用鍵的最左邊的首碼,或如果鍵不是UNIQUEPRIMARY KEY(換句話說,如果聯接不能基於關鍵字選擇單個行的話),則使用ref。如果使用的鍵僅僅匹配少量行,該聯接類型是不錯的。ref可以用於使用=<=>操作符的帶索引的列。

ref_or_null:該聯接類型如同ref,但是添加了MySQL可以專門搜索包含NULL值的行。在解決子查詢中經常使用該聯接類型的優化。

index_merge:該聯接類型表示使用了索引合併優化方法。在這種情況下,key列包含了使用的索引的清單,key_len包含了使用的索引的最長的關鍵元素。

unique_subquery:該類型替換了下面形式的IN子查詢的refvalue IN (SELECT primary_key FROMsingle_table WHERE some_expr);unique_subquery是一個索引查找函數,可以完全替換子查詢,效率更高。

index_subquery:該聯接類型類似於unique_subquery。可以替換IN子查詢,但只適合下列形式的子查詢中的非唯一索引:value IN (SELECT key_column FROM single_table WHERE some_expr)

range:只檢索給定範圍的行,使用一個索引來選擇行。key列顯示使用了哪個索引。key_len包含所使用索引的最長關鍵元素。在該類型中ref列為NULL。當使用=<>>>=<<=IS NULL<=>BETWEEN或者IN操作符,用常量比較關鍵字列時,可以使用

range index:該聯接類型與ALL相同,除了只有索引樹被掃描。這通常比ALL快,因為索引檔通常比資料檔案小。

all:對於每個來自於先前的表的行組合,進行完整的表掃描。如果表是第一個沒標記const的表,這通常不好,並且通常在它情況下很差。通常可以增加更多的索引而不要使用ALL,使得行能基於前面的表中的常數值或列值被檢索出。
ossible_keyspossible_keys列指出MySQL能使用哪個索引在該表中找到行。注意,該列完全獨立於EXPLAIN輸出所示的表的次序。這意味著在possible_keys中的某些鍵實際上不能按生成的表次序使用。

keykey列顯示MySQL實際決定使用的鍵(索引)。如果沒有選擇索引,鍵是NULL。要想強制MySQL使用或忽視possible_keys列中的索引,在查詢中使用FORCE INDEXUSE INDEX或者IGNORE INDEX

key_lenkey_len列顯示MySQL決定使用的鍵長度。如果鍵是NULL,則長度為NULL。注意通過key_len值我們可以確定MySQL將實際使用一個多部關鍵字的幾個部分。

refref列顯示使用哪個列或常數與key一起從表中選擇行。

rowsrows列顯示MySQL認為它執行查詢時必須檢查的行數。

Extra:該列包含MySQL解決查詢的詳細資訊。

DistinctMySQL發現第1個匹配行後,停止為當前的行組合搜索更多的行。

Not exists

MySQL能夠對查詢進行LEFT JOIN優化,發現1個匹配LEFT JOIN標準的行後,不再為前面的的行組合在該表內檢查更多的行。
range checked for each record (index map: #)MySQL沒有發現好的可以使用的索引,但發現如果來自前面的表的列值已知,可能部分索引可以使用。對前面的表的每個行組合,MySQL檢查是否可以使用rangeindex_merge訪問方法來索取行。
Using filesortMySQL需要額外的一次傳遞,以找出如何按排序順序檢索行。通過根據聯接類型流覽所有行並為所有匹配WHERE子句的行保存排序關鍵字和行的指針來完成排序。然後關鍵字被排序,並按排序順序檢索行。
Using index:從只使用索引樹中的資訊而不需要進一步搜索讀取實際的行來檢索表中的列資訊。當查詢只使用作為單一索引一部分的列時,可以使用該策略。
Using temporary:為了解決查詢,MySQL需要創建一個臨時表來容納結果。典型情況如查詢包含可以按不同情況列出列的GROUP BYORDER BY子句時。
Using whereWHERE子句用於限制哪一個行匹配下一個表或發送到客戶。除非你專門從表中索取或檢查所有行,如果Extra值不為Using where並且表聯接類型為ALLindex,查詢可能會有一些錯誤。
Using sort_union(...), Using union(...), Using intersect(...):這些函數說明如何為index_merge聯接類型合併索引掃描。
Using index for group-by:類似於訪問表的Using index方式,Using index for group-by表示MySQL發現了一個索引,可以用來查詢GROUP BYDISTINCT查詢的所有列,而不要額外搜索硬碟訪問實際的表。並且,按最有效的方式使用索引,以便對於每個組,唯讀取少量索引條目。

通過相乘EXPLAIN輸出的rows列的所有值,你能得到一個關於一個聯接如何的提示。這應該粗略地告訴你MySQL必須檢查多少行以執行查詢。當你使用max_join_size變數限制查詢時,也用這個乘積來確定執行哪個多表SELECT語句。

SQL Server 效能調校實戰

* 64Bit 的 Windows Server 要配上 64Bit 的 SQL Server,不然會影響效能
(例如:避免在 64bit windows server 上安裝 32bit sql server ... 就杯具了)

* 要經常注意資料的成長率
(雖然資料庫預設會自動長大,但是也會有來不及長大就掛點的危機,而且,這還很常發生)

* 效能的檢測與評估,可以分為三大部分:硬體資源配置規劃,資料庫設計,應用程式設計
(必須要對症下藥才會有效,不然可以花了錢又製造更多的災難)

* 可使用 ALTER [Table] REBUILD 來重建資料表 (瘦身)
TechNet Ref : ALTER TABLE (Transact-SQL)

* 備份起來之後大量刪除會造成大量的交易記錄(Transaction Log)
MSDN Ref : Managing the Transaction Log
(註:這邊忘了,是要先備份起來避免,還是怎樣 ... 總之每次刪除都會產生紀錄這樣)

* Do not View on View
(檢視表拿出來再做檢視表,這樣的效能一定不好)

* Table 與 Index 的 File Group 可以分開設置
(利用硬體的特性,分開存放在不同實體才有效果,放在同一顆硬碟的不同磁碟區其實並沒有意義)

* 核心處理資料時,只讀取 8k per page (要注意)

* 設計時的資料型態(DataType)規劃很重要

* 設計時的索引(Index)規劃也很重要

* 64Bit 不會檢查 AWE
TechNet Ref : 使用 AWE

* SQL Server 設定中的選項不要亂勾選
(選項之間有可能互相影響)

* 硬體會影響的部分可分為 CPU / HD / RAM / NETWORK

* File Group / Table / Index 相關

* 2 Tier / 3 Tier / SQL Command / Transaction / Lock 等都有可能影響效能

* Do not over 6 indexes in one table.
(數大不一定美)

* 使用 LIKE 比對字串,會比使用 SubString(0 ~ n) 來的快速
假使你的字串比對都是「從頭開始」,選用 SubString 不見得會變快

* 使用 SET 改變資料會比 Loop Cursor 要來得有效率

* 定期量測效能指標 :
- response time
- concurrent user
- data process per min
- cpu usage
- HD IOPS
- ram usage

* 分割 Table 與 Index 可以提升效能

* 使用資料壓縮來縮減 Table 與 Index 的大小
(跟壓縮有關的功能似乎有版本限制)

* 內建效能調校工具 :
- Database Tuning Advisor
- SQL Server Profiler

* SanpShot 會使用到 tempdb

* 設定交易隔離等級

* 利用資料分割鎖定 與 減少磁碟爭用

補充 : tempdb 資料庫的並行增強功能

* 使用資源管理員控制資源的使用量

* 使用資料收集器收集資料,並且分析與產生報表

* 資料壓縮 :
- Row 壓縮 : 適合 Online : 2% ~ 5% CPU 使用量, 20% 壓縮比
- Page 壓縮 : 適合 History : 10% ~ 15% CPU 使用量, 60% ~ 70% 壓縮比
(不只檔案縮小,連記憶體的使用量也會減少,代價是 CPU 使用率)

* 使用 Filtered Indexes (篩選索引) 可以提升索引效率
語法 : CREATE INDEX [IndexName] ON [TableName]([ColumnName]) WHERE TYPE='[TypeName]';

* 向上擴充支援 NUMA, 256 顆 CPU, 2TB RAM, 50 Instance ... 等

* 向外擴充支援 SSAS, Service Broker, Data Dependent Routing, 分割檢視表(可橫切) ... 等

* 分割檢視表中的定序很重要,計算型欄位不可以有索引,可搭配 INSTEAD OF 觸發程序

* 查詢通知可以使用系統內建的預存程序 sp_DispatcherProc

* 查詢通知在 ADO.NET 的相關元件為 : SQLNotifcation, SqlDepandency

* 資料異動擷取(CDC)
- 異動資料擷取的基本概念
- 啟用異動資料擷取
- 異動資料擷取資料表 (Transact-SQL)

* 變更追蹤(CD) ... 此處缺肉 orz

* 點對點交易式複寫有 分散查詢 + 容錯 的特性

* 可擴充共用資料庫(唯讀)

* 使用系統的效能監視器(Performance Counter)來監測伺服器的健康狀況
也可以找出"基準線",讓將來更容易分辨異常
記錄下來的數值,要注重其相對性,尤其是與之前的紀錄數據做比較
注意:這邊主要是要知道發生了什麼(WHAT),而不是為何(WHY)或是如何(HOW)

* 重要的效能物件與計數器 : ... (這邊投影片上有,我就不多打了)

* 善用 SQL Trace (server side) 與 SQL Profiler (client side)

* SQL Profiler 的死結圖示可以很直覺的看到死結的事發現場 XD

* SQL Profiler 可以整合效能監視器,同時紀錄系統效能

* Database Engine Tuning Advisor 可以由各種紀錄的來源,來分析出效能調整的建議
(這工具非常強大,不過似乎也有版本的限制 ...)

* 伺服器端的好幫手 - Management Studio
可以產生各種好用的報表,以及即時的活動監視器,用來觀察目前伺服器運行的狀況
更貼心的是,下方直接就將"最近且費時的查詢"的前幾名列出來了,黑名單就在這!!

* 動態管理檢視與動態管理函數
內建許多功能,像是可以找出 TOP 20 MAX CPU Time (in one day) 這樣的資訊


* 非同步 mirror : use 2 snapshots on mirror
(Tip : join-in tempdb)

* 正確的 DataType 是很重要的
(當你每筆資料省下了 50 Bytes,當有 4000 萬筆資料時,就省下約 2GB 的空間)

* 可以使用 VS2008 做壓力測試模擬

* 可以使用 Performance Dashboard Report 尋找 Missing Index (重要)
- SQL Server 2005 Performance Dashboard Reports Download

* DataType Matching is important.
(假使兩端資料型態不吻合,有可能影響執行計畫的流程,進而造成效能降低)

* 資料庫正規畫與 JOIN 指令,大量的 JOIN 會直接影響效能
(正規化與反正規化的取捨,要靠經驗與專案需求而定,沒有標準答案)

* 觀察 T-SQL 指令的執行計畫,進而改善查詢的效能

* 使用者自訂函數,在某些情況可以改善效能