程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 數據庫知識 >> SqlServer數據庫 >> 關於SqlServer >> T-SQL查詢優化各種方法

T-SQL查詢優化各種方法

編輯:關於SqlServer
我們知道不同的SQL語句可能會返回相同的結果,但是這些語句的性能不同,使用高效率的查詢尤其在如今數據量井噴的時代顯得尤為重要。我們將以T-SQL為例講解數據庫優化的技術。

語句

首先對T-SQL查詢語句作一個回顧,語句格式如下

(5) SELECT (5-2) DISTINCT (5-3) TOP(<top_specification>) (5-1) <select_list>
(1) FROM (1-J) <left_table> <join_type> JOIN <right_table> ON <on_predicate>
| (1-A) <left_table> <apply_type> APPLY <right_table_expression> AS <alias>
| (1-P) <left_table> PIVOT(<pivot_specification>) AS <alias>
| (1-U) <left_table> UNPIVOT(<unpivot_specification>) AS <alias>
(2) WHERE <where_predicate>
(3) GROUP BY <group_by_specification>
(4) HAVING <having_predicate>
(6) ORDER BY <order_by_list>;
編號表示查詢處理的各個階段。

SELECT 語句中使用列表名比使用*查詢更快,如
SELECT COUNT(column_name) from table_name
而不要使用

SELECT COUNT(*) from table_name


能用WHERE做條件過濾時不要使用HAVING,因為HAVING階段時已經返回了所有行,導致效率低。


WHERE從句,使用LIKE作模糊匹配比在WHERE子句中使用函數好(同樣,在WHERE子句中也盡量避免使用表達式),例如
SELECT column_name1 FROM table_name WHERE column_name2 LIKE 'prefix%'
當然,如果能全文掃描則盡量使用全文掃描,部分匹配將導致全表掃描從而降低效率。



條件過濾使用BETWEEN.. AND 比使用 >=, <=好,因為後者會導致全表掃描。


為了不進行全表掃描,可以考慮在WHERE 、ORDER BY 後面跟的列上建立索引。


避免在WHERE子句中使用OR,否則會導致全表掃描,可以考慮改成
SELECT column_name FROM table_name WHERE <predicate1>
UNION ALL
SELECT column_name FROM table_name WHERE <predicate2>


強行使用索引掃描的方法為
SELECT column_name FROM table_name WITH(INDEX(index_name)) WHERE <predicate>


字段設計

數據類型盡量用數字型,數字型的比較比字符型的快很多。
數據類型盡量小,這裡的盡量小是指在滿足可以預見的未來需求的前提下的。
盡量不要允許NULL,除非必要,可以用NOT NULL+DEFAULT代替。
少用TEXT和IMAGE,二進制字段的讀寫是比較慢的,而且,讀取的方法也不多,大部分情況下最好不用。
自增字段要慎用,不利於數據遷移。
索引設計

在設計階段,可以根據功能和性能的需求進行初步的索引設計,這裡需要根據預計的數據量和查詢來設計索引,可能與將來實際使用的時候會有所區別。

關於索引的選擇,應改主意:


根據數據量決定哪些表需要增加索引,數據量小的可以只有主鍵。
根據使用頻率決定哪些字段需要建立索引,選擇經常作為連接條件、篩選條件、聚合查詢、排序的字段作為索引的候選字段。
把經常一起出現的字段組合在一起,組成組合索引,組合索引的字段順序與主鍵一樣,也需要把最常用的字段放在前面,把重復率低的字段放在前面。
一個表不要加太多索引,因為索引影響插入和更新的速度。


注意事務和鎖

事務是數據庫應用中和重要的工具,它有原子性、一致性、隔離性、持久性這四個屬性,很多操作我們都需要利用事務來保證數據的正確性。在使用事務中我們需要做到盡量避免死鎖、盡量減少阻塞。具體以下方面需要特別注意:

A、事務操作過程要盡量小,能拆分的事務要拆分開來。

B、 事務操作過程不應該有交互,因為交互等待的時候,事務並未結束,可能鎖定了很多資源。

C、 事務操作過程要按同一順序訪問對象。

D、提高事務中每個語句的效率,利用索引和其他方法提高每個語句的效率可以有效地減少整個事務的執行時間。

E、 盡量不要指定鎖類型和索引,SQL SERVER允許我們自己指定語句使用的鎖類型和索引,但是一般情況下,SQL SERVER優化器選擇的鎖類型和索引是在當前數據量和查詢條件下是最優的,我們指定的可能只是在目前情況下更有,但是數據量和數據分布在將來是會變化的。

F、 查詢時可以用較低的隔離級別,特別是報表查詢的時候,可以選擇最低的隔離級別(未提交讀)。



注意臨時表和表變量的用法

在復雜系統中,臨時表和表變量很難避免,關於臨時表和表變量的用法,需要注意:

A、如果語句很復雜,連接太多,可以考慮用臨時表和表變量分步完成。

B、 如果需要多次用到一個大表的同一部分數據,考慮用臨時表和表變量暫存這部分數據。

C、 如果需要綜合多個表的數據,形成一個結果,可以考慮用臨時表和表變量分步匯總這多個表的數據。

D、其他情況下,應該控制臨時表和表變量的使用。

E、 關於臨時表和表變量的選擇,很多說法是表變量在內存,速度快,應該首選表變量,但是在實際使用中發現,這個選擇主要考慮需要放在臨時表的數據量,在數據量較多的情況下,臨時表的速度反而更快。

F、 關於臨時表產生使用SELECT INTO和CREATE TABLE + INSERT INTO的選擇,我們做過測試,一般情況下,SELECT INTO會比CREATE TABLE + INSERT INTO的方法快很多,但是SELECT INTO會鎖定TEMPDB的系統表SYSOBJECTS、SYSINDEXES、SYSCOLUMNS,在多用戶並發環境下,容易阻塞其他進程,所以我的建議是,在並發系統中,盡量使用CREATE TABLE + INSERT INTO,而大數據量的單個語句使用中,使用SELECT INTO。

G、 注意排序規則,用CREATE TABLE建立的臨時表,如果不指定字段的排序規則,會選擇TEMPDB的默認排序規則,而不是當前數據庫的排序規則。如果當前數據庫的排序規則和TEMPDB的排序規則不同,連接的時候就會出現排序規則的沖突錯誤。一般可以在CREATE TABLE建立臨時表時指定字段的排序規則為DATABASE_DEFAULT來避免上述問題。



子查詢的用法


子查詢是一個 SELECT 查詢,它嵌套在 SELECT、INSERT、UPDATE、DELETE 語句或其它子查詢中。任何允許使用表達式的地方都可以使用子查詢。

子查詢可以使我們的編程靈活多樣,可以用來實現一些特殊的功能。但是在性能上,往往一個不合適的子查詢用法會形成一個性能瓶頸。

如果子查詢的條件中使用了其外層的表的字段,這種子查詢就叫作相關子查詢。相關子查詢可以用IN、NOT IN、EXISTS、NOT EXISTS引入。

關於相關子查詢,應該注意:

A、NOT IN、NOT EXISTS的相關子查詢可以改用LEFT JOIN代替寫法。比如:


SELECT PUB_NAME
FROM PUBLISHERS
WHERE PUB_ID NOT IN
(SELECT PUB_ID
FROM TITLES
WHERE TYPE = 'BUSINESS')

可以改寫成:

SELECT A.PUB_NAME
FROM PUBLISHERS A LEFT JOIN TITLES B
ON B.TYPE = 'BUSINESS' AND
A.PUB_ID=B. PUB_ID
WHERE B.PUB_ID IS NULL


SELECT TITLE
FROM TITLES
WHERE NOT EXISTS
(SELECT TITLE_ID
FROM SALES
WHERE TITLE_ID = TITLES.TITLE_ID)

可以改寫成:

SELECT TITLE
FROM TITLES LEFT JOIN SALES
ON SALES.TITLE_ID = TITLES.TITLE_ID
WHERE SALES.TITLE_ID IS NULL

B、 如果保證子查詢沒有重復 ,IN、EXISTS的相關子查詢可以用INNER JOIN 代替。比如:

SELECT PUB_NAME
FROM PUBLISHERS
WHERE PUB_ID IN
(SELECT PUB_ID
FROM TITLES
WHERE TYPE = 'BUSINESS')

可以改寫成:

SELECT DISTINCT A.PUB_NAME

FROM PUBLISHERS A
  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved