一次SQL調(diào)優(yōu)數(shù)據(jù)庫性能問題后的過程(300W)
更新時間:2010年03月30日 14:26:55 作者:
對單表超過300w+數(shù)據(jù)的Web應(yīng)用程序進行測試后發(fā)現(xiàn)了一些功能、性能問題,采取了以下辦法來進行調(diào)整
將絕大部分的SQL查詢改為存儲過程,這樣的操作毫無疑問可以提高部分性能。
凡是使用“select * from xxx”的操作一律具體到所需字段。
使用join連接2個以上大量數(shù)據(jù)的表,且基礎(chǔ)數(shù)據(jù)表變化不大的查詢一律使用視圖,并為此視圖建立索引。理由來自SQL Server聯(lián)機幫助手冊: “對于標準視圖而言,為每個引用視圖的查詢動態(tài)生成結(jié)果集的開銷很大,特別是對于那些涉及對大量行進行復(fù)雜處理(如聚合大量數(shù)據(jù)或聯(lián)接許多行)的視圖。如果在查詢中頻繁地引用這類視圖,可通過對視圖創(chuàng)建唯一聚集索引來提高性能。對視圖創(chuàng)建唯一聚集索引后,結(jié)果集將存儲在數(shù)據(jù)庫中,就像帶有聚集索引的表一樣。
對視圖創(chuàng)建索引的另一個好處是:優(yōu)化器可以在未直接在 FROM 子句中指定某一視圖的查詢中使用該視圖的索引。這樣一來,可從索引視圖檢索數(shù)據(jù)而無需重新編碼,由此帶來的高效率也使現(xiàn)有查詢獲益?!?
凡是使用 "select count(*) from xxx" 或是"select count(id) from xxx”(此處id為主鍵)的查詢,一律改為”select count(1) from xxx”,理論上采用*來做聚合值,SQL Server會自動尋覓最合適的字段以進行聚合,但這樣仍然會占用系統(tǒng)開銷,即使主鍵也沒有1來得快。
對于多條件的組合查詢,我們一般會寫成”where ((@condition is null) or (condition=@condition))”形式的存儲過程條件來進行查詢,但這樣的操作會因為”is null ”導(dǎo)致性能問題,反復(fù)實地檢測后采用了”where 1 = 1 ”,然后根據(jù)條件“IF @condition IS NOT NULL SET @sqlText=@sqlText+' AND Condition=''' + @Condition +'''',最后 “exec sp_executesql @sqlText” 的方式,這樣確實可帶來明顯的性能提升,分析應(yīng)是”is null ”或”is not null”導(dǎo)致了索引失效,進行了全表掃描。
對使用row_number()函數(shù)的表建立合適的索引,必須要有最合適的索引才能避免重建索引時的全表row_number()運算帶來的性能問題,而且索引的方向也很重要,比如時間類的索引用降序往往比升序性能高。
這個不是性能問題,但也很重要,在存儲過程中應(yīng)使用scope_identity()函數(shù)來獲得最新的標量,而不是@@Identity這個全局變量,因為@@Identity會受到觸發(fā)器的影響而失去正確值。
凡是使用“select * from xxx”的操作一律具體到所需字段。
使用join連接2個以上大量數(shù)據(jù)的表,且基礎(chǔ)數(shù)據(jù)表變化不大的查詢一律使用視圖,并為此視圖建立索引。理由來自SQL Server聯(lián)機幫助手冊: “對于標準視圖而言,為每個引用視圖的查詢動態(tài)生成結(jié)果集的開銷很大,特別是對于那些涉及對大量行進行復(fù)雜處理(如聚合大量數(shù)據(jù)或聯(lián)接許多行)的視圖。如果在查詢中頻繁地引用這類視圖,可通過對視圖創(chuàng)建唯一聚集索引來提高性能。對視圖創(chuàng)建唯一聚集索引后,結(jié)果集將存儲在數(shù)據(jù)庫中,就像帶有聚集索引的表一樣。
對視圖創(chuàng)建索引的另一個好處是:優(yōu)化器可以在未直接在 FROM 子句中指定某一視圖的查詢中使用該視圖的索引。這樣一來,可從索引視圖檢索數(shù)據(jù)而無需重新編碼,由此帶來的高效率也使現(xiàn)有查詢獲益?!?
凡是使用 "select count(*) from xxx" 或是"select count(id) from xxx”(此處id為主鍵)的查詢,一律改為”select count(1) from xxx”,理論上采用*來做聚合值,SQL Server會自動尋覓最合適的字段以進行聚合,但這樣仍然會占用系統(tǒng)開銷,即使主鍵也沒有1來得快。
對于多條件的組合查詢,我們一般會寫成”where ((@condition is null) or (condition=@condition))”形式的存儲過程條件來進行查詢,但這樣的操作會因為”is null ”導(dǎo)致性能問題,反復(fù)實地檢測后采用了”where 1 = 1 ”,然后根據(jù)條件“IF @condition IS NOT NULL SET @sqlText=@sqlText+' AND Condition=''' + @Condition +'''',最后 “exec sp_executesql @sqlText” 的方式,這樣確實可帶來明顯的性能提升,分析應(yīng)是”is null ”或”is not null”導(dǎo)致了索引失效,進行了全表掃描。
對使用row_number()函數(shù)的表建立合適的索引,必須要有最合適的索引才能避免重建索引時的全表row_number()運算帶來的性能問題,而且索引的方向也很重要,比如時間類的索引用降序往往比升序性能高。
這個不是性能問題,但也很重要,在存儲過程中應(yīng)使用scope_identity()函數(shù)來獲得最新的標量,而不是@@Identity這個全局變量,因為@@Identity會受到觸發(fā)器的影響而失去正確值。
相關(guān)文章
使用BULK INSERT大批量導(dǎo)入數(shù)據(jù) SQLSERVER
使用BULK INSERT大批量導(dǎo)入數(shù)據(jù) SQLSERVER,需要的朋友可以參考下。2011-12-12SQLSERVER語句的執(zhí)行時間顯示的統(tǒng)計結(jié)果是什么意思
在SQL語句調(diào)優(yōu)的時候,大部分都會查看語句執(zhí)行時間,究竟SQLSERVER顯示出來的統(tǒng)計結(jié)果是什么意思,接下來為您一一解釋,感興趣的朋友可以了解下2013-01-01跨數(shù)據(jù)庫實現(xiàn)數(shù)據(jù)交流
這篇文章主要介紹了跨數(shù)據(jù)庫實現(xiàn)數(shù)據(jù)交流的兩種方式,一是通過鏈接服務(wù)器,二是使用OPENDATASOURCE/OPENROWSET連接遠程服務(wù)器,需要的朋友可以參考下2015-08-08SQL SERVER 與ACCESS、EXCEL的數(shù)據(jù)轉(zhuǎn)換
SQL SERVER 與ACCESS、EXCEL的數(shù)據(jù)轉(zhuǎn)換...2006-07-07