青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

牽著老婆滿街逛

嚴以律己,寬以待人. 三思而后行.
GMail/GTalk: yanglinbo#google.com;
MSN/Email: tx7do#yahoo.com.cn;
QQ: 3 0 3 3 9 6 9 2 0 .

30 分鐘快快樂樂學 SQL Performance Tuning

轉載自:http://www.cnblogs.com/WizardWu/archive/2008/10/27/1320055.html


有些程序員在撰寫數據庫應用程序時,常專注于 OOP 及各種 framework 的使用,卻忽略了基本的 SQL 語句及其「性能 (performance) 優化」問題。版工曾聽過臺灣某半導體大廠的新進程序員,所組出來的一段 PL/SQL 跑了好幾分鐘還跑不完;想當然爾,即使他的 AJAX 及 ooxx 框架用得再漂亮,系統性能也會讓使用者無法忍受。以下是版工整理出的一些數據庫規劃、SQL performance tuning 簡單心得,讓長年鉆研 .NET、AJAX、一堆高深 ooxx framework,卻無暇研究 SQL statement 的程序員,透過最短時間對本帖的閱讀,能避免踩到一些 SQL 的性能地雷

(注:本帖的 SQL 語句皆經過測試可正常執行無誤。有興趣實驗者,可直接拷貝后,粘貼至 SQL Server 中執行。)

1、數據庫設計與規劃

• Primary Key 字段的長度盡量小,能用 small integer 就不要用 integer。例如員工數據表,若能用員工編號當主鍵,就不要用身分證號碼。

• 一般字段亦同。若該數據表要存放的數據不會超過 3 萬筆,用 small integer 即可,不必用 integer。

• 文字字段若長度固定,如:身分證號碼,就不要用 varchar 或 nvarchar,應該用 char 或 nchar。

• 文字字段若長度不固定,如:地址,則該用 varchar 或 nvarchar。除了可節省存儲空間外,存取硬盤時也會較有效率。

• 設計字段時,若其值可有可無,最好也給一個默認值,并設成「不允許 NULL」(一般字段默認為「允許 NULL」)。因為 SQL Server 在存放和查詢有 NULL 的數據表時,會花費額外的運算動作 [2]。

• 若一個數據表的字段過多,應垂直切割成兩個以上的數據表,并可用同名的 Primary Key 一對多連結起來,如:Northwind 的 Orders、Order Details 數據表。以避免在存取數據時,以「集簇索引 (clustered index)」掃描時會加載過多的數據,或修改數據時造成互相鎖定或鎖定過久。

------------------------------

2、適當地建立索引

• 記得自行幫 Foreign Key 字段建立索引,即使是很少被 JOIN 的數據表亦然。

• 替常被查詢或排序的字段建立索引,如:常被當作 WHERE 子句條件的字段。

• 用來建立索引的字段,長度不宜過長,不要用超過 20 個 Byte 的字段,如:地址。

• 不要替內容重復性高的字段建立索引,如:性別;反之,若重復性低的字段則適合建立索引,如:姓名。

• 不要替使用率低的字段建立索引,以免浪費硬盤空間

• 不宜替過多字段建立索引,否則反而會影響到「INSERTUPDATEDELETE」能,尤其是以OLTP (聯機事務處理在線交易)」為主的網站數據庫。

• 若數據表存放的數據很少,就不必刻意建立索引。否則可能數據庫沿著存放索引的「樹狀結構」(Balanced Tree) 去搜尋索引中的數據,反而比掃描整個數據表還慢。

• 若查詢時符合條件的數據很多,則透過「非集簇索引 (non-clustered index)」搜尋的能,反而 可能不如整個數據表逐筆掃描。

• 建立「集簇索引」的字段選擇至為重要,會影響到整個索引結構的能。要用來建立「集簇索引」的字段,務必選擇「整數」類型 (鍵值會較小)、唯一、不可為 NULL。

------------------------------

3、適當地使用索引

• 有些書籍會提到,使用LIKE、%做模糊查詢時,即使您已替某個字段建立索引 (如下方代碼的 CustomerID 字段),但以常量字符開頭才會使用到索引,若以萬用字符 (%) 開頭則不會使用索引,如下所示:

USE Northwind;
GO
SELECT * FROM Orders WHERE CustomerID LIKE 'D%';    --使用索引
SELECT * FROM Orders WHERE CustomerID LIKE '%D';    --不使用索引

在 SQL Server 2005 執行完成后按 Ctrl + L,可檢閱如下圖的「執行計劃」。


圖 1 可看出「查詢最佳化程序」有使用到索引做搜尋


圖 2 在此的集簇索引掃描,并未直接使用索引,能上幾乎只等于掃描整個數據表

但經版工反復測試,這種語法是否會使用到索引,抑或會逐筆掃描,并非絕對的。仍要看所下的查詢關鍵詞,以及字段內 所存儲的數據內容而定。但對于存儲數據筆數龐大的數據表,最好還是少用 LIKE 做模糊查詢。


• 以下的運算符會造成「負向查詢」,常會讓「查詢最佳化程序」無法有效地使用索引,最好能用其它運算符和語法改寫 (經版工測試,并非有負向運算符,就絕對無法使用索引):
NOT 、 != 、 <> 、 !> 、 !< 、 NOT EXISTS 、 NOT IN 、 NOT LIKE

• 避免讓 WHERE 子句中的字段,去做字符串的串接或數字運算,否則可能導致「查詢最佳化程序」無法直接使用索引,而改采集簇索引掃描(經版工測試并非絕對)。

• 數據表中的數據,會依照「集簇索引」字段的順序存放,因此當您下 BETWEEN、GROUP BY、ORDER BY 時若有包含「集簇索引」字段,由于數據已在數據表中排序好,因此可提升查詢速度。

• 若使用「復合索引」,要注意索引順序上的第一個字段,才適合當作過濾條件。

------------------------------

4、避免在 WHERE 子句中對字段使用函數

對字段使用函數,也等于對字段做運算或串接的動作,一樣可能會讓「查詢最佳化程序」無法有效地使用索引。但真正對能影響最重大的,是當您的數據表內若有 10 萬筆數據,則在查詢時就需要呼叫函數 10 萬次,這點才是真正的能殺手。程序員應注意,在系統開發初期可能感覺不出差異,但當系統上線且數據持續累積后,這些語法細節所造成的能問題就會逐步浮現

SELECT * FROM Orders WHERE DATEPART(yyyy, OrderDate) = 1996 AND DATEPART(mm, OrderDate)=7
可改成
SELECT * FROM Orders WHERE OrderDate BETWEEN '19960701' AND '19960731'
 
SELECT * FROM Orders WHERE SUBSTRING(CustomerID, 1, 1) = 'D'
可改成
SELECT * FROM Orders WHERE CustomerID LIKE 'D%'

注意當您在下 UPDATE、DELETE 語句時,若有采用 WHERE 子句,也應符合上述原則。。

------------------------------

5、AND 與 OR 的使用

在 AND 運算中,「只要有一個」條件有用到索引 (如下方的 CustomerID),即可大幅提升查詢速度,如下圖 3 所示:

SELECT * FROM Orders WHERE CustomerID='VINET' AND Freight=32.3800 --使用索引,會出現下圖 3 的畫面
 
SELECT * FROM Orders WHERE Freight=32.3800 --不使用索引,會出現上圖 2 的畫面
 
 

圖 3

但在 OR 運算中,則要「所有的」條件都有可用的索引,才能使用索引來提升查詢速度。因此 OR 運算符的使用必須特別小心

若您將上方 AND 的范例,邏輯運算符改成 OR 的話,如下所示:

SELECT * FROM Orders WHERE CustomerID='VINET' OR Freight=32.3800

 

由于無法有效地使用索引,也會出現圖 2 的畫面。

在使用 OR 運算符時,只要有一個條件 (字段) 沒有可用的索引,則其它所有的條件 (字段) 都有索引也沒用,只能如圖 2 般,把整個數據表或整個集簇索引都掃描過,以逐筆比對是否有符合條件的數據。


據網絡上文件的說法 [1],上述的 OR 運算語句,我們還可用 UNION 聯集適當地改善,如下:

SELECT * FROM Orders WHERE CustomerID='VINET' 
UNION 
SELECT * FROM Orders WHERE Freight=32.3800

此時您再按 Ctrl + L 檢閱「執行計劃」,會發現上半段的查詢會使用索引,但下半段仍用集簇索引掃描,對能不無小補。

------------------------------

6、適當地使用子查詢

相較于「子查詢 (Subquery)」,若能用 JOIN 完成的查詢,一般會比較建議使用后者。原因除了 JOIN 的語法較容易理解外,在多數的情況下,JOIN 的能也會比子查詢較佳;但這并非絕對,也有的情況可能剛好相反。

我們知道子查詢可分為「獨立子查詢」和「關聯子查詢」兩種,前者指子查詢的內容可單獨執行,后者則無法單獨執行,亦即外層查詢的「每一次」查詢動作都需要引用內層查詢的數據,或內層查詢的「每一次」查詢動作都需要參考外層查詢的數據。

以下我們看一個比較極端的例子 [2]。若我們希望所有查詢出來的數據,都能另外給一個自動編號,版工我在之前的文章「ASP.NET 數據分頁第一篇 - 探討分頁原理及 SQL Server 2005 的 ROW_NUMBER 函數」中有介紹過,可用 SQL Server 2005 中新增的 ROW_NUMBER 函數輕易地達成,且 ROW_NUMBER 函數還能再加上「分群 (PARTITION BY)」等功能,而且執行性能極佳。


圖 4 將 Orders 數據表的 830 筆數據都撈出來,并在右側給一組自動編號

現在我們要如上圖 4 般,將 Northwind 數據庫 Orders 數據表的 830 筆數據都撈出來,并自動給一組編號,若用 ROW_NUMBER 函數的寫法如下所示,而且能極佳,只要 2 ms (毫秒),亦即千分之二秒。

SET STATISTICS TIME ON

SELECT OrderID, ROW_NUMBER() OVER(ORDER BY OrderID) AS 編號 
FROM dbo.Orders

但如果是傳統的「子查詢」寫法,或 輔以 AS 關鍵詞的「衍生數據表」的語法,寫法必須如下 (拷貝后在 SQL Server 中實際可執行)

SET STATISTICS TIME ON

SELECT OrderID, 
  (SELECT COUNT(*) FROM dbo.Orders AS 內圈
   WHERE 內圈.OrderID <= 外圈.OrderID) AS 編號    
FROM dbo.Orders AS 外圈 
ORDER BY 編號

但這種舊寫法,會像先前所提到的,外層 (外圈) 查詢的「每一次」查詢動作都需要引用內層 (內圈) 查詢的數據。以上方示例而言,外層查詢的每一筆數據,都要等內層查詢「掃描整個數據表」并作比對和計數,因此 830 筆數據每一筆都要重復掃描整個數據表 830 次,所耗用的時間也因此爆增至 170 ms。

若您用相同的寫法,去查詢 AdventureWorks 數據庫中,有 31,465 筆數據的 Sales.SalesOrderHeader 數據表,用 ROW_NUMBER 函數要 677 ms,還不到 1 秒鐘;但用子查詢的話,居然要高達 233,835 ms,將近快 4 分鐘的時間。

-- 用 ROW_NUMBER 的寫法,改查詢 AdventureWorks 數據庫 (31,465 筆數據,要 677 ms,還不到 1 秒鐘)

SELECT SalesOrderID, ROW_NUMBER() OVER(ORDER BY SalesOrderID) AS rownum
FROM Sales.SalesOrderHeader
 
-- 用子查詢的寫法,改查詢 AdventureWorks 數據庫 (31,465 筆數據,要 233,835 ms,將近 4 分鐘)

SELECT SalesOrderID, 
  (SELECT COUNT(*) FROM Sales.SalesOrderHeader AS 內圈
   WHERE 內圈.SalesOrderID <= 外圈.SalesOrderID) AS 編號 
FROM Sales.SalesOrderHeader AS 外圈 
ORDER BY 編號


雖然這是較極端的范例,但由此可知子查詢的撰寫,在使用上不可不慎,尤其是「關聯子查詢」。程序員在系統開發初期、數據量還很少時感受不到此種 SQL 語法的重大陷阱;但等到系統上線幾個月或一兩年后,就會有反應遲緩的現象, 不可不慎

注:AS 關鍵詞及「衍生數據表」是 SQL Server 的語法,「衍生數據表」只會存在內存中,AS 關鍵詞的作用是賦予一個別名。過去許多必須用暫存數據表或 View (
視圖) 的情況,現在都可以用「衍生數據表」來取代,如此一來不但可以降低數據庫管理工作的負擔,亦可提升查詢性能。

------------------------------

7、其他查詢技巧

• DISTINCT、ORDER BY 語法,會讓數據庫做額外的計算。此外聯集的使用,若沒有要剔除重復數據的需求,使用 UNION ALL 會比 UNION 更,因為后者會加入類似 DISTINCT 的算法。

• 在 SQL Server 2005 中,存取數據庫對象時,最好明確指定該對象的「結構描述 (Schema)」,也就是使用兩節式名稱,如下方代碼所示。否則若呼叫者的預設 Schema 不是 dbo,則 SQL Server 在執行時,會先尋找該使用者預設 Schema 所搭配的對象,找不到的話才會轉而使用預設的 dbo,會多耗費尋找的時間。因此若要執行一個叫做 dbo.mySP1 的 Stored Procedure,應使用以下的兩節式名稱:
EXEC dbo.mySP1

------------------------------
 

8、盡可能用 Stored Procedure 取代應用程序直接存取數據表

Stored Procedure 除了經過事先編譯、能較好以外,亦可節省 SQL 語句傳遞的網絡頻寬,也方便商業邏輯的重復使用。再搭配自訂函數和 View 的使用,將來若要修改數據表結構、重新切割或反正規化時亦較方便。

------------------------------

9、盡可能在數據來源層,就先過濾數據

使用 SELECT 語法時,盡量避免傳回所有的數據至前端而不設定 WHERE 等過濾條件。雖然 ASP.NET 中 SqlDataSource、ObjectDataSource 控件的 FilterExpression 可再做篩選,GridView 控件的 SortExpression 可再做排序,但會多消耗掉數據庫的系統資源、web server 的內存和網絡頻寬。最好還是在數據庫和數據來源層,就先用 SQL 條件式 Stored Procedure 篩選出所要的資料。有關這方面,網友們可參考版工我之前寫的「ASP.NET 數據分頁」系列的四篇帖子。

------------------------------

結論:
本文的觀念,不管是寫 SQL statement、Stored Procedure、自訂函數或 View 皆然。本文只是挑出程序員較容易犯的 SQL 語法能問題,以期能在短時間瀏覽過本文后,在寫 ADO.NET 程序時能修正以往隨興的 SQL 語句撰寫習慣。文中提到的幾點,只不過是 SQL 語法能議題的入門。市面上有很多更進階的書籍,例如:「The Art of SQL」、「SQL Tuning」,亦有針對 Oracle 或 SQL Server 數據庫撰寫的 performance tuning 相關書籍,有興趣者可自行翻閱


------------------------------------------------------------
------------------------------------------------------------

參考文件:

[1] SQL 查詢最佳化 (網際烏托邦):
http://www.ithome.com.tw/plog/index.php?op=ViewArticle&articleId=5421&blogId=620

------------------------------

參考書籍:

[2] SQL Server 2005 Performance Tuning 效能調校 (臺灣書籍)
作者:胡百敬、姚巧枚、劉承修
出版社:悅知出版社
http://tlsj.tenlong.com.tw/WebModule/BookSearch/bookSearchViewAction.do?isbn=9789866761225&sid=41966

[3] SQL Server 2005 完全實戰 (臺灣書籍)
作者:章立民
出版社:碁峰出版社
http://tlsj.tenlong.com.tw/WebModule/BookSearch/bookSearchViewAction.do?isbn=9789861810454&sid=31975

------------------------------

相關文件:

[4] 臺大醫院數據庫分割疏失,系統幾近停擺 (ITHome):
http://www.ithome.com.tw/itadm/article.php?c=43597

[5]] 當 DataGrid 遇見100 萬筆資料:
http://blog.sina.com.tw/4907/article.php?pbgid=4907&entryid=3921

[6] ASP.NET 2.0 GridView 范例集 - 「4-8-4、GridView 的效能」:
http://blog.csdn.net/Code6421/archive/2007/12/22/1958167.aspx

[7] 有關開啟頁面時,一次加載數千筆數據的能問題:
http://www.blueshop.com.tw:80/board/show.asp?subcde=BRD200709141021458MV

------------------------------

posted on 2011-04-15 09:18 楊粼波 閱讀(846) 評論(0)  編輯 收藏 引用


只有注冊用戶登錄后才能發表評論。
網站導航: 博客園   IT新聞   BlogJava   博問   Chat2DB   管理


青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            欧美理论在线播放| 亚洲视频每日更新| 亚洲精品乱码久久久久久蜜桃麻豆| 欧美日韩亚洲综合一区| 另类春色校园亚洲| 国产精品视频大全| 亚洲激情电影中文字幕| 在线播放亚洲| 欧美伊人精品成人久久综合97| 亚洲视频1区2区| 欧美激情按摩| 欧美福利电影在线观看| 一区二区三区我不卡| 午夜精品影院| 亚洲女人小视频在线观看| 欧美猛交免费看| 亚洲欧洲日本专区| 亚洲人精品午夜在线观看| 久久综合久久久| 免费视频一区二区三区在线观看| 国产精品视频观看| 亚洲一区二区三区中文字幕 | 国产午夜久久| 一个色综合导航| 中文日韩在线视频| 欧美日韩国产黄| 日韩午夜免费| 亚洲一区二区高清| 国产精品视频精品视频| 亚洲欧美精品中文字幕在线| 亚洲欧美精品在线观看| 国产精品久久久久久久久免费樱桃 | 久久久久久穴| 久久亚洲春色中文字幕久久久| 国产日韩欧美另类| 久久久99爱| 欧美成人午夜| 日韩视频在线一区二区| 欧美另类videos死尸| 一本色道久久综合狠狠躁的推荐| 亚洲一级片在线观看| 国产精品嫩草99av在线| 午夜精品久久久久久99热软件| 久久久999精品| 18成人免费观看视频| 免费成人高清在线视频| 日韩亚洲精品在线| 午夜欧美电影在线观看| 国产综合色在线| 欧美大片在线观看一区| 夜夜嗨网站十八久久| 久久国产日韩| 亚洲日本激情| 国产精品美女久久久久久2018| 欧美专区在线观看一区| 欧美激情亚洲| 午夜精品一区二区三区在线播放| 国产亚洲成年网址在线观看| 看欧美日韩国产| 日韩视频―中文字幕| 久久精品1区| 亚洲精品日韩欧美| 国产精品日韩欧美一区二区| 久久精品女人天堂| 99国产麻豆精品| 毛片基地黄久久久久久天堂| 一区二区三区日韩精品视频| 狠狠操狠狠色综合网| 欧美日韩激情网| 久久国产直播| 99视频精品全国免费| 狼人社综合社区| 午夜老司机精品| 亚洲激情偷拍| 国产曰批免费观看久久久| 欧美激情中文字幕乱码免费| 午夜精品成人在线视频| 亚洲精品在线二区| 老色鬼久久亚洲一区二区| 亚洲一区在线看| 亚洲精品免费一二三区| 国产亚洲精品高潮| 欧美午夜精品理论片a级大开眼界| 欧美一区二视频| 一区二区三区日韩在线观看| 亚洲福利视频一区二区| 久久精品论坛| 亚洲欧美成人网| 亚洲伦理在线| 在线播放一区| 国语自产偷拍精品视频偷| 欧美系列精品| 欧美日韩一级片在线观看| 免费视频一区二区三区在线观看| 欧美在线影院| 午夜在线精品| 亚洲欧美国产制服动漫| 一本色道久久| 一本色道久久综合亚洲精品高清| 亚洲国产小视频在线观看| 暖暖成人免费视频| 久久在线免费观看| 久久精品午夜| 久久精品五月| 久久尤物电影视频在线观看| 久久国产日韩| 久久久久成人精品| 久久精视频免费在线久久完整在线看| 亚洲淫性视频| 亚洲欧美日本国产专区一区| 亚洲欧美经典视频| 欧美亚洲在线视频| 性色一区二区| 久久久精品视频成人| 久久福利视频导航| 久久综合色婷婷| 麻豆精品91| 亚洲国产欧美精品| 亚洲精品偷拍| 亚洲素人在线| 欧美亚洲三级| 久久综合给合久久狠狠色 | 国产精品香蕉在线观看| 国产精品久久久久久久久久三级 | 国产精品久久久久久久午夜片 | 国产精品系列在线播放| 国产欧美精品一区aⅴ影院| 国产精品影视天天线| 国产亚洲午夜高清国产拍精品| 国产亚洲欧美日韩日本| 亚洲第一搞黄网站| 亚洲久久一区二区| 亚洲男女自偷自拍图片另类| 欧美一区二区成人| 美国三级日本三级久久99| 最新亚洲视频| 亚洲综合国产| 美女视频黄免费的久久| 欧美日韩国产123| 国产情人节一区| 亚洲高清在线播放| 亚洲性感激情| 久久婷婷久久| 亚洲精品乱码久久久久久久久| 亚洲一级在线| 嫩草国产精品入口| 国产精品三级视频| 在线日韩欧美视频| 亚洲伊人色欲综合网| 久久噜噜噜精品国产亚洲综合 | 亚洲欧美日韩在线一区| 久久综合给合| 国产精品夜夜嗨| 亚洲乱码国产乱码精品精可以看| 午夜久久一区| 亚洲激情在线观看| 亚洲欧美日韩国产一区二区三区| 美女精品在线观看| 国产女主播在线一区二区| 亚洲欧洲精品一区二区三区不卡 | 日韩亚洲综合在线| 久久精品国产一区二区三区| 亚洲欧洲精品一区二区| 欧美在线国产精品| 欧美三级电影精品| 亚洲精品乱码久久久久久日本蜜臀| 欧美一区三区二区在线观看| 亚洲国产视频a| 久久米奇亚洲| 国产亚洲在线| 欧美亚洲视频一区二区| 亚洲精品在线视频观看| 老巨人导航500精品| 国产日韩欧美一区二区三区四区| 一区二区免费在线视频| 欧美freesex8一10精品| 午夜精品福利一区二区蜜股av| 欧美视频网站| 99视频在线精品国自产拍免费观看| 老司机aⅴ在线精品导航| 午夜电影亚洲| 国产精品专区一| 欧美亚洲免费高清在线观看| 日韩一级欧洲| 欧美视频在线不卡| 一区二区不卡在线视频 午夜欧美不卡在 | 欧美在线观看视频一区二区| 国产精品久久久99| 亚洲无人区一区| 99精品视频一区| 欧美日韩黄视频| 一区二区三区精品国产| 亚洲国产裸拍裸体视频在线观看乱了| 久久久噜噜噜久久久| 国内精品写真在线观看| 久久国产精品99久久久久久老狼 | 亚洲欧美怡红院| 国产精品日韩久久久久| 欧美一区国产二区| 欧美亚洲日本国产|