SQL Server2005 數據優化

查詢性能優化 (SQL Server Compact Edition)

 

您可以通過優化所用查詢來提高 SQL Server 2005 Compact Edition (SQL Server Compact Edition) 應用程序性能。下列各節概述了可以用來優化查詢性能的方法。

創建有用的索引是提高查詢性能的最重要方法之一。有用的索引可幫助減少在查找數據時所需使用的磁盤 I/O 操作數和系統資源量。

若要創建有用的索引,您必須瞭解下列知識:數據的使用方式,查詢的類型及其運行頻率,以及查詢處理器如何使用索引快速查找數據。

當選擇要創建何種索引時,請檢查您的關鍵查詢,其性能將對用戶體驗產生極大的影響。需要創建專門輔助這些查詢的索引。在添加索引後,重新運行查詢以查看是否提高了性能。如果未提高,則刪除索引。

與大多數性能優化方法一樣,此方法也有一些缺點。例如,使用較多索引時,SELECT 查詢的運行速度很可能會更快。但是,DML(INSERT、UPDATE 和 DELETE)操作的速度將顯著減慢,因爲對於每個操作都必須維護更多的索引。因此,如果您的查詢主要包含 SELECT 語句,則使用較多的索引是非常有幫助的。如果您的應用程序需要執行許多 DML 操作,就有必要控制創建的索引數。

SQL Server Compact Edition 包括對顯示計劃的支持,顯示計劃可以幫助評估和優化查詢。除了 SQL Server Compact Edition 使用的只是一部分運算符之外,SQL Server Compact Edition 使用與 SQL Server 2005 相同的顯示計劃架構。有關詳細信息,請參閱位於 http://go.microsoft.com/fwlink/?LinkId=38029 的 Microsoft 顯示計劃架構。

下面幾節介紹有關創建有用索引的其他信息。

創建高選擇性索引

對關鍵查詢的 WHERE 子句中使用的列創建索引,通常會提高性能。但是,這取決於索引選擇性的高低。選擇性是指符合條件的行數與總行數之比。如果比率較低,索引就是高選擇性的。它可以篩選掉大多數行,從而大大減小結果集的大小。因此,這樣的索引就是要創建的有用索引。與之相比,選擇性低的索引就沒有那麼有用。

唯一索引具有最高的選擇性。只有一行可以匹配,這對只希望返回一行的查詢是最有用的。例如,唯一 ID 列的索引可幫助您快速查找特定的行。

通過對 SQL Server Compact Edition 表運行 sp_show_statistics 存儲過程,您可以評估索引的選擇性。例如,若要評估兩個列(“Customer ID”和“Ship Via”)的選擇性,可以運行下列存儲過程:

sp_show_statistics_steps 'orders', 'customer id';

 

RANGE_HI_KEY RANGE_ROWS EQ_ROWS DISTINCT_RANGE_ROWS

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

ALFKI               0            7                   0

ANATR               0            4                   0

ANTON               0           13                   0

AROUT               0           14                   0

BERGS               0           23                   0

BLAUS               0            8                   0

BLONP               0           14                   0

BOLID               0            7                   0

BONAP               0           19                   0

BOTTM               0           20                   0

BSBEV                0           12                   0

CACTU               0            6                   0

CENTC               0            3                   0

CHOPS               0           12                   0

COMMI               0            5                   0

CONSH               0            4                   0

DRACD               0            9                   0

DUMON               0            8                   0

EASTC               0           13                   0

ERNSH               0           33                   0

(90 rows affected)

sp_show_statistics_steps 'orders', 'reference3';

 

RANGE_HI_KEY RANGE_ROWS EQ_ROWS DISTINCT_RANGE_ROWS

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

1               0            320                   0

2               0            425                   0

3               0          333                   0

(3 rows affected)

 

結果表明“Customer ID”列的重複程度更低。這意味着其索引的選擇性將比“Ship Via”列的索引的選擇性要高。

有關使用這些存儲過程的詳細信息,請參閱 sp_show_statistics (SQL Server Compact Edition)sp_show_statistics_steps (SQL Server Compact Edition)sp_show_statistics_columns (SQL Server Compact Edition)

創建多列索引

多列索引是單列索引的自然擴展。對於計算與預先指定的一組鍵列匹配的篩選表達式,多列索引是非常有用的。例如,組合索引 CREATE INDEX Idx_Emp_Name ON Employees ("Last Name" ASC, "First Name" ASC) 有助於計算下列查詢:

  • ... WHERE "Last Name" = 'Doe'
  • ... WHERE "Last Name" = 'Doe' AND "First Name" = 'John'
  • ... WHERE "First Name" = 'John' AND "Last Name" = 'Doe'

但是,它對下面的查詢是沒有用的:

  • ... WHERE "First Name" = 'John'

在創建多列查詢時,應該將選擇性最高的列放在鍵中的最左端。這樣,在匹配多個表達式時,就可以使索引的選擇性更高。

避免對小表創建索引

小表是指內容只適合一個或幾個數據頁的表。因爲進行表掃描通常效率更高,所以要避免對非常小的表創建索引。這會節省加載和處理索引頁的開銷。不對非常小的表創建索引,可以避免優化器選擇此類索引。

SQL Server Compact Edition 按 4 Kb 一頁來存儲數據。使用以下公式可以計算出近似的頁數,儘管實際的頁數由於存儲引擎開銷的原因可能會稍微多一些。

<列的總大小(字節)> * <行數>

<頁數> = -----------------------------------------------------------------

4096

例如,假設一個表的架構如下:

列名類型(大小)

訂單 ID

INTEGER(4 字節)

產品 ID

INTEGER(4 字節)

單價

MONEY(8 字節)

數量

SMALLINT(2 字節)

折扣

REAL(4 字節)

此表包含 2820 行。按照公式,存儲該表數據需要大約 16 頁:

<頁數> = ((4 + 4 + 8 + 2 + 4) * 2820) / 4096 = 15.15 頁

建議始終對主鍵創建索引。另外,對外鍵創建索引通常也非常有用。這是因爲通常使用主鍵和外鍵來聯接表。創建這些鍵的索引後,優化器可以使用效率更高的索引聯接算法。如果您的查詢使用其他列來聯接表,由於相同的原因,對這些列創建索引通常也非常有用。

在創建主鍵和外鍵的約束後,SQL Server Compact Edition 將自動爲其創建索引並在優化查詢時加以利用。請記住使用較小的主鍵和外鍵。這樣,聯接的運行速度會更快。

與篩選子句一起使用索引

索引可以用於提高某些類型的篩選子句的計算速度。雖然所有篩選子句都會減小查詢的最終結果集,但是某些篩選子句還可以幫助減小所需掃描的數據量。

搜索參數 (SARG) 可指定精確匹配、值的範圍或由 AND 聯接的兩項或多項的連接,因此能夠限制搜索範圍。搜索參數採用以下格式之一:

  • 列 運算符 <常量或變量>
  • <常量或變量> 運算符 列

SARG 運算符包括 =、>、<、>=、<=、IN、BETWEEN,有時還包括 LIKE(在進行前綴匹配時,如 LIKE 'John%')。SARG 可以包括由 AND 聯接的多個條件。SARG 還可以是匹配特定值的查詢,例如:

  • "Customer ID" = 'ANTON'
  • 'Doe' = "Last Name"

SARG 也可以是匹配一定範圍的值的查詢,例如:

  • "Order Date" > '1/1/2002'
  • "Customer ID" > 'ABCDE' AND "Customer ID" < 'EDCBA'
  • "Customer ID" IN ('ANTON', 'AROUT')

不使用 SARG 運算符的表達式無法提高性能,因爲 SQL Server Compact Edition 查詢處理器必須評估所有行,以確定是否滿足篩選子句。因此,對於不使用 SARG 運算符的表達式,索引是沒有用的。非 SARG 運算符包括 NOT、<>、NOT EXISTS、NOT IN、NOT LIKE 和內部函數。

在確定基表的訪問方法時,SQL Server Compact Edition 優化器將確定是否存在 SARG 子句的索引。如果存在索引,優化器將通過計算返回多少行來評估索引。然後,優化器會估計通過使用索引查找符合條件的行的開銷。如果使用索引的開銷比表掃描的開銷低,優化器將選擇索引訪問。如果在 SARG 中使用索引的第一列或預先指定的一組列,且 SARG 指定了限制搜索範圍的下限、上限或同時執行了這兩者,則索引很可能是有用的。

響應時間是查詢返回第一條記錄所用的時間。總時間是查詢返回所有記錄所用的時間。對於交互式應用程序,響應時間是很重要的,因爲這決定了用戶要等待多長時間,才能通過看到第一條返回記錄確定查詢正在處理中。對於批處理應用程序,總時間反映了總體吞吐量。您必須確定應用程序和查詢的性能標準,然後才能相應地進行設計。

例如,假設查詢返回 100 條記錄,前五條記錄用來填充一個列表。在此情況下,您不關心返回全部 100 條記錄所用的時間。相反,您只希望查詢快速返回前幾條記錄,以便填充列表。

可以執行許多查詢操作,而無需存儲中間結果。這些操作稱爲管道操作。管道操作的示例是映射、選擇和聯接。通過這些操作執行的查詢可以立即返回結果。其他操作(如 SORT 和 GROUP-BY)需要使用所有輸入信息,纔可以將結果返回到父操作。這就是我們所說的要求具體化的操作。由於具體化的原因,通過這些操作執行的查詢通常會有初始延遲。在此初始延遲之後,此類查詢通常也可以很快地返回記錄。

具有響應時間要求的查詢應避免具體化。例如,與使用排序相比,使用索引執行 ORDER-BY 的響應時間更短。下一節將對此進行詳細說明。

對 ORDER-BY/GROUP-BY/DISTINCT 列創建索引以縮短響應時間

ORDER-BY、GROUP-BY 和 DISTINCT 操作都是排序類型的操作。SQL Server Compact Edition 查詢處理器使用兩種方法進行排序。如果記錄已經按索引進行排序,則處理器只使用索引。否則,處理器必須先使用臨時工作表對記錄進行排序。在 CPU 較慢並且內存較低的設備上,這樣的預先排序會造成顯著的初始延遲,因此,在響應時間比較重要時,應該避免預先排序。

在使用多列索引的情況下,爲了使 ORDER-BY 或 GROUP-BY 處理特定索引,ORDER-BY 或 GROUP-BY 列必須與預先指定的一組索引列匹配,而且順序要完全相同。例如,索引 CREATE INDEX Emp_Name ON Employees ("Last Name" ASC, "First Name" ASC) 有助於優化下列查詢:

  • ... ORDER BY / GROUP BY "Last Name" ...
  • ... ORDER BY / GROUP BY "Last Name", "First Name" ...

但對下列查詢,它並沒有幫助:

  • ... ORDER BY / GROUP BY "First Name" ...
  • ... ORDER BY / GROUP BY "First Name", "Last Name" ...

爲了使 DISTINCT 操作處理多列索引,映射列表必須與所有索引列匹配,儘管順序不必完全相同。上面的索引有助於優化下列查詢:

  • ... DISTINCT "Last Name", "First Name" ...
  • ... DISTINCT "First Name", "Last Name" ...

但對下列查詢,它並沒有幫助:

  • ... DISTINCT "First Name" ...
  • ... DISTINCT "Last Name" ...
注意:
如果您的查詢始終返回唯一行,請不要指定 DISTINCT 關鍵字,因爲它只會增加開銷。

 

 

 

有時可以重寫子查詢以使用 JOIN,從而提高性能。創建 JOIN 的好處是,可以按與查詢所定義順序不同的順序評估表。使用子查詢的好處是,通常不必掃描子查詢中的所有行就可以計算子查詢表達式。例如,EXISTS 子查詢可以在找到第一個符合條件的行時就返回 TRUE。

注意:
SQL Server Compact Edition 查詢處理器始終會重寫 IN 子查詢以使用 JOIN。對包含 IN 子查詢子句的查詢,不必使用此方法。

 

 

例如,若要確定包含至少一個折扣率大於或等於 25% 的項的所有訂單,可以使用下面的 EXISTS 子查詢:

SELECT "Order ID" FROM Orders O

WHERE EXISTS (SELECT "Order ID"

FROM "Order Details" OD

WHERE O."Order ID" = OD."Order ID"

AND Discount >= 0.25)

您也可以使用 JOIN 對其進行重寫:

SELECT DISTINCT O."Order ID" FROM Orders O INNER JOIN "Order Details"

OD ON O."Order ID" = OD."Order ID" WHERE Discount >= 0.25

使用 Outer JOIN 進行限制

OUTER JOIN 與 INNER JOIN 的處理方式是不同的:對於 INNER JOIN 表,優化器會嘗試重新排列聯接順序,而對於 OUTER JOIN 表則不會。外部表(LEFT OUTER JOIN 中的左表和 RIGHT OUTER JOIN 中的右表)將首先訪問,然後纔會訪問內部表。這一固定的聯接順序可能會導致執行計劃不能達到最優。

注意:
SQL Server Compact Edition 查詢處理器假定 INNER JOIN 包括的列上有索引(由用戶或數據庫創建)。

 

 

如果應用程序運行的一系列查詢僅有一些常量是不同的,則可以通過使用參數化查詢來提高性能。例如,若要按不同的客戶返回訂單,可以運行下面的查詢:

SELECT "Customer ID" FROM Orders WHERE "Order ID" = ?

通過只編譯一次查詢然後多次執行編譯好的計劃,參數化查詢可以提供更好的性能。從編程上講,必須始終保持包含緩存查詢計劃的命令對象。如果破壞以前的命令對象再創建新的命令對象,會破壞緩存的計劃。這要求重新編譯查詢。如果必須交替運行多個參數化查詢,則可以創建幾個命令對象,每個命令對象都包含一個參數化查詢的緩存執行計劃。這樣,就可以有效避免重新編譯所有這些查詢了。

SQL Server Compact Edition 查詢處理器是查詢關係數據庫中存儲的數據的強大工具。但是,任何查詢處理器都會造成一定程度的內部開銷。在開始真正地執行計劃之前,查詢處理器必須編譯、優化和生成執行計劃。對於很快完成的簡單查詢,尤其是這樣。因此,您自己執行查詢有時可以大大提高性能。如果每一毫秒對您的關鍵組件都很重要,建議您考慮自己執行簡單查詢這一替代方法。對於複雜的大型查詢,這種工作最好還是留給查詢處理器去做。

例如,假設您希望查找按訂單 ID 排列的一系列訂單的客戶 ID。有兩種方法可以實現此操作。第一種方法是對於每一次查找都執行下列步驟:

  1. 打開 Orders 基表
  2. 使用特定的“Order ID”查找行
  3. 檢索“Customer ID”

或者,對於每一次查找都發出以下查詢:

SELECT "Customer ID" FROM Orders WHERE "Order ID" = <the specific order id>

 

與手動解決方案相比,基於查詢的解決方案更簡單但速度更慢,因爲 SQL Server Compact Edition 查詢處理器需要將 SQL 聲明語句轉換爲與手動執行時相同的三個操作。隨後,這三個步驟將按順序執行。選用哪種方法將取決於在應用程序中簡易性和性能哪方面更重要。

發佈了37 篇原創文章 · 獲贊 0 · 訪問量 6萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章