sql性能優化總結:
最近隨着數據越來越多,數據庫性能問題暴露的越來越嚴重。幾百萬,上千萬,甚至過億的數據處理速度會非常的慢。
下面對工作中遇到的問題做下總結,希望以後能對日後的工作有所幫助。
不同的sql語句有不同的性能問題,只有要找到性能差的原因,才能對症下藥。
首先說下性能判斷的方法:
一.性能分析器:Microsoft的SQL Profiler
Oracle的Audit和AWR ,oracle也可以用PLsql中的explain plan(黃色燈泡)來分析。
二.性能相關SQL語句:(目前先拿sql server 說,其他版本慢慢補充。)
- -- 建聚集索引
- CREATE CLUSTERED INDEX INDEX_Userid ON T_UserInfo ( Userid)
- -- 建非聚集索引
- CREATE NONCLUSTERED INDEX INDEX_Userid ON T_UserInfo ( Userid)
- -- 刪除索引
- DROP INDEX T_UserInfo. INDEX_Userid
- -- 顯示有關由 Transact-SQL 語句生成的磁盤活動量的信息
- SET STATISTICS IO ON
- -- 關閉有關由 Transact-SQL 語句生成的磁盤活動量的信息
- SET STATISTICS IO OFF
- -- 顯示 [ 返回有關語句執行情況的詳細信息,並估計語句對資源的需求 ]
- SET SHOWPLAN_ALL ON
- -- 關閉 [ 返回有關語句執行情況的詳細信息,並估計語句對資源的需求 ]
- SET SHOWPLAN_ALL OFF
*注意:(掃盲高手跳過)聚集索引就是表存儲的時候的順序,一張表只能有一個聚集索引。非聚集索引就表存儲的結構不是按索引結構存儲的。
具體使用方法看sql server幫助說的很全了,這裏總結SHOWPLAN_ALL需要注意的幾點:
1.Index Seek(索引查找) :索引查找意味着查詢優化器使用了數據表上的非聚集索引來查找數據。
性能通常會很快,尤其是當只有少數的數據行被返回時。
2.Clustered Index Seek:聚集索引查找。這指查詢優化器使用了數據表上的聚集索引來查找數據,性能很快。
3.Clustered Index Scan:聚集索引掃描。 聚集索引掃描與表掃描相似,不同的是聚集索引掃描是在一個建有聚集索引的數據表上執行的。和一般的表掃描一樣,聚集索引掃描可能表明存在效能問題。
上面3項是性能比較好快的,下面幾項從性能上來說是不理想的,避免的越多性能越快:
1.Table Scan:表掃描。如果看到這個信息,就說明數據表上沒有聚集索引,或者查詢優化器沒有使用索引來查找。
2.Index or table scans:索引或者表掃描。可能意味着需要更好的或者額外的索引。
3.Bookmark Lookups:書籤查找。考慮修改當前的聚集索引,使用覆蓋索引,限制 SELECT 語句中的字段數量。
4.Filter:過濾。在WHERE從句中移除用到的任何函數,不要在 SQL 語句中包含視圖,可能需要額外的索引。
5.Sort:排序。如果查詢的數據本身就是按一定順序排序的,或者查詢結果對排序無要求,那就不需要排序。
寫sql文的注意事項:
1.創建索引,在大量甚至海量數據的表裏有索引檢索的速度要比沒有索引檢索快上幾個數量級。
2.視圖,視圖本身不能建立索引,但是視圖可以應用引用表的索引,當引用表的字段結構未變化時。
3.IN , NOT IN ==>替換方案EXISTS, NOT EXISTS
尤其是NOT IN不能應用表的索引,建議不使用。在 JOIN 關聯後 也最好不要使用IN.
但是如果是 IN (12,21,13,14) 這種還是可以使用, 這種用法比 OR ....OR...OR 要快一點兒。
4. <> , !=
不等於操作符是永遠不會用到索引的,因此對它的處理只會產生全表掃描。
a!=0 改爲 a>0 or a<0
a!=’’ 改爲 a>’’
5. > 或者<
a>1 改爲 a>=1 , b < 2 改爲 b<=2;
這裏涉及到索引的應用問題,利用>= 或 <=能夠更好的應用索引。
6. WHERE 後的條件順序
mysql 採用從左至右的順序解析WHERE子句,那些可以過濾掉最大數量記錄的條件寫在WHERE子句的前面。
ORACLE 採用從右至左的順序解析WHERE子句,那些可以過濾掉最大數量記錄的條件寫在WHERE子句的末尾。
7. GROUP BY
Group BY 後面跟的分組條件越多越慢,切忌不要無謂的添加分組條件。
8. 在sql文中轉換類型會非常的慢 儘量不要使用 to_char, to_date 等函數。
9. SELECT子句中避免使用 *
WHERE exsits (select * from XX_table) ==> WHERE exsits (select id from XX_table)