SQL Server 2014新特性——基數評估(白皮書閱讀筆記)


基數評估

目錄

基數評估... 1

說明... 2

基數評估准確的重要性... 2

模型假設... 3

啟用新的基數評估... 3

驗證基數評估的版本... 3

在遷移到新的基數評估前要測試... 4

校驗基數評估... 4

偏差問題... 4

需要手動處理的變化... 4

避免因為新的CE造成性能下降... 4

SQL Server 2014中的修改... 5

增加多個謂詞的相關性的假設... 5

修改超出統計信息范圍的評估... 5

Join評估算法修改... 5

Join包含(Containment)假設的修改... 6

不同值計數評估的變化... 7

診斷輸出... 7

新基數評估的調優方法... 8

修改數據庫兼容級別... 8

使用跟蹤標記... 8

基礎調優方法... 8

 

 

說明

查詢優化器的目的是為了找出有效的執行計划,根據cost運算,取出cost最小的計划,作為執行計划。其中影響cost最重要的一項就是基數評估(估計行數)。SQL Server 2014對基數評估做了修改。

基數評估准確的重要性

基數評估提供以下信息:

1.響應行數評估(the distribution of data

2.不同值個數評估(distinct value count

3.重復值個數,作為上一級基數評估(duplicate count as input for parent operator estimation calculations

基數評估是通過計算統計信息的出來的結果,而統計信息通過優化器創建或者通過索引創建。

統計信息分為:頭,密度向量,直方圖。

當統計信息存在的時候基數評估器使用密度向量和直方圖來計算評估。

基數評估主要回答以下幾個問題:

1.一個或多個謂詞或過濾幾行

2.2個表之間的連接謂詞會過濾幾行

3.預計一個指定列集合中有多少不同值(distinct value

Sql server中有2種謂詞:1.過濾謂詞,2.連接謂詞

基數評估(CE):試圖回答wherejoinhaving這些謂詞的選擇性。也試圖回答groupdistinct的不同值(distinct value)。

CE的計算從圖形執行計划中是從右到左的,下一級的評估作為上一級計算評估的輸入。

 

每個執行計划中的運算符都有評估值輸入,這個值決定了優化器使用什么算法的操作符,同時也決定了最終的執行計划。所以如果評估出現偏差,會導致執行計划選擇出現偏差,導致無法選出一個高效的執行計划。

評估出現偏差會出現以下結果:

如果評估過小:

1.原本可以使用並行計划更加有效的,現在使用串行計划

2.不合適的join算法

3.不合適的索引選擇,和索引訪問方法

如果評估過大:

1.原本使用串行計划更加有效,現在使用並行計划

2.不可合適的join算法

3.不合適的索引選擇,和索引訪問方法

4.過多的內存分配

5.內存浪費和沒必要的並發

 

模型假設

內核有以下假設:

Independence:假設,在沒有額外的相關信息之外,數據在不同的列是沒有關聯的

Uniformity:在統計信息的直方圖的step,數據分布式均勻分布在step上的。

Containment 2個表連接,那么高密度的一定被低密度的包含。

Inclusion:如果對一列對常數過濾,那么認為這個常數數據一定存在在這個列中。

啟用新的基數評估

當數據庫的兼容級別為120的時候,就是啟用了新的基數評估,默認使用新的基數評估。

但是可以通過查詢跟蹤標記來指定:

2312:在兼容級別低於120的時候使用新的基數評估

9481:在兼容級別在120下,使用老的基數評估

驗證基數評估的版本

可以從圖形執行計划或者XML執行計划中找到CardinalityEstimationModelVersion,如果為120就是新的基數評估,70就是老的基數評估。

在遷移到新的基數評估前要測試

新的基數評估雖然總體提示了性能,但是對個別查詢來說,會被影響,性能變差,所以要測試。

1.在類似生產環境下,測試大多數的負荷

2.可以先遷移到sql server 2014,但是使用不運行在120兼容級別

3.也可以到120兼容級別,但是在全局范圍開9481跟蹤標記

4.新建數據庫推薦使用默認會使用120兼容級別。

校驗基數評估

沒有什么特別的就是通過實際值和評估值對個對比。

偏差問題

評估值偏差,是存在的,那么多少算是偏差太大了?其實沒有一個固定的值,主要是看以下2點:

1.偏差是不是造成了資源過度使用

2.偏差是不是造成了特定查詢的性能問題

如果任意一個出現問題的話,那么就能認為偏差太大了。

需要手動處理的變化

只有評估值變化的情況下,看性能是否下降超過預期,如果超過要進行手動干預。

如果評估值和老CE一樣,並且計划沒有什么變化,就不需要處理。

避免因為新的CE造成性能下降

1.能夠從新基數評估得到性能優化的查詢,就使用新基數評估,其他的進行重新調整。

2.有好處的查詢使用新的基數評估,其他的使用跟蹤標記9481

3.使用老的基數評估,特定的查詢可以指定跟蹤標記2312

4.直接調試有問題的sql

5.使用老的基數評估

SQL Server 2014中的修改

增加多個謂詞的相關性的假設

在沒有多列統計信息的情況下,SQL Server優化器會認為謂詞之間是不相關的。

老的基數評估:各個謂詞的選擇度相乘

新的基數評估:選擇度從低到高排序,然后使用以下公式:

修改超出統計信息范圍的評估

如果超出統計信息范圍,那么老的基數評估就認為不存在,評估行數為1

新的基數評估會用,密度*總行數來當評估。

Join評估算法修改

簡單Join

老的基數評估是以線性增長的方式一步一步對齊2個直方圖。(根本不知道是怎么玩的)

新的基數評估,使用相對簡單的join評估算法,只是用直方圖的最大最小邊界來對齊。(文章並沒有給出詳細的算法很坑爹)。

新的基數評估是用這種原則,很容易發現評估值不夠准確。

Join條件

多個join條件,對於老的基數評估來說,是獨立的謂詞,是用選擇度相乘的方法來組合。

新的基數評估,是用2個不同值個數(distinct value count)中較小的一個,然后乘以2邊的平均頻率。(搞不懂

Join帶相等和不相等的謂詞

老的基數評估,是獨立的謂詞,是用選擇度相乘的方法來組合。

新的基數評估,認為大表小標多對1的關系。即大表中的一行,必定存在於表的一樣與之對應。這個算法把大表的評估作為評估。(這個簡單

Join包含(Containment)假設的修改

如果是等值連接,那么就會假設這個列表2邊都是存在的。如果存在join表上有非join謂詞,老的基數評估那么會認為一些級別的相關,這種相關叫做簡單包含(Simple Containment)。

老的基數評估的JOIN評估,假設在使用join謂詞之前,任意存在的謂詞會縮小直方圖,而謂詞之間是不相關的。老CE用這樣的評估方式會讓評估值偏大。

USE [AdventureWorks2012];

GO

 

SELECT [od].[SalesOrderID], [od].[SalesOrderDetailID]

FROM    Sales.[SalesOrderDetail] AS [od]

INNER JOIN Production.[Product] AS [p]

ON [od].[ProductID] = [p].[ProductID]

WHERE   [p].[Color] = 'Red' AND

[od].[ModifiedDate] = '2008-06-29 00:00:00.000'

OPTION (QUERYTRACEON 9481); -- CardinalityEstimationModelVersion 70

 

新的基數評估是使用基本包含(Base Containment),新的基數評估,是直接從基表上面獲取選擇度,而不是經過謂詞過濾之后。

不同值計數評估的變化

對於新的基數評估和老的相比在多對多連接中,不同值計數評估相差很小。如果join條件會放大基數,老的基數評估可能會不准確。

新的基數評估根據join謂詞和非join謂詞選擇不同值。新的基數評估使用環境基數(ambient cardinality),環境基數是group by或者distinct列的最小不同值集合(The new CE uses “ambient cardinality”, which is the cardinality of the smallest set of joins that contains the GROUP BY or DISTINCT columns.)。

診斷輸出

使用新的xeventquery_optimizer_estimate_cardinality來輸出

CREATE EVENT SESSION [CardinalityEstimate] ON SERVER

ADD EVENT sqlserver.query_optimizer_estimate_cardinality

ADD TARGET package0.event_file( SET filename = N'S:\CE\CE_Data.xel' ,

                                  max_rollover_files =( 2 ) )

WITH ( MAX_MEMORY = 4096 KB ,

        EVENT_RETENTION_MODE = ALLOW_SINGLE_EVENT_LOSS ,

        MAX_DISPATCH_LATENCY = 30 SECONDS ,

        STARTUP_STATE = OFF );

GO

 

-- Start the session

ALTER EVENT SESSION [CardinalityEstimate] ON SERVER STATE=START;

 

--

-- Your workload to be analyzed executed here (or in another session)

--

 

-- Stop the session after the workload is executed

ALTER EVENT SESSION [CardinalityEstimate] ON SERVER STATE=STOP;

也可以使用A first look at the query_optimizer_estimate_cardinality XE event中的方法。

新基數評估的調優方法

修改數據庫兼容級別

如果新的CE出現性能問題,可以通過修改兼容級別回到以前的CE版本。

使用跟蹤標記

可以使用QUERYTRACEON來使用查詢級別選項,這個跟蹤標記會影響一個語句的CE級別。

基礎調優方法

統計信息丟失

統計信息丟失,但是沒有及時創建,應該查看是否啟用了統計信息自動創建選項。

統計信息過期

統計信息可能太老,導致查詢性能問題,考慮是否要手動跟新統計信息。

統計信息采樣率

表如果數據分布不均衡,無法在直方圖上表現,看看統計信息頭中的rows sampledrows的差距,可以考慮使用調整采樣率或者直接fullscan

過濾統計信息(filtered statistics)

對於大的表存在數據不均衡,過濾統計信息可以很好的解決這個問題。

注意點:過濾統計信息的更新閥值是基於表的,而不是過濾謂詞。

在沒有recompile提示之下,過濾索引和過濾統計信息不會被應用到參數化的字段過濾。(In the absence of a RECOMPILE hint, filtered indexes and statistics will not be used in conjunction with parameterization that refers to the filter column.)。

多列統計信息

自動創建統計信息,只會創建單列的,多列統計信息是手工創建的,創建多列統計信息可以提高評估的准確性。提高查詢性能。

參數敏感性(Parameter Sensitivity

參數敏感性是因為數據分布不均衡,參數化的執行計划會以第一次運行的時候的參數來創建,如果數據不均衡,參數變化,會導致執行計划不是很理想的狀況。可以加上OPTIMIZE FOR或者RECOPILE來解決。

表變量

SQL Server 2014上面表變量沒有相關的統計信息的,如果要在表變量上存大量的數據建議使用臨時表。

多語句用戶定義表變量函數

和表變量差不多,多語句表變量函數也沒有統計信息,只是用一個固定的基數100。考慮使用內聯表變量函數。

內聯表變量函數式沒有函數體的,直接return 一個表

而多語句表變量函數式有函數體的。

XML Reader表變量函數操作

使用nodes() XQUERY方法如果沒有XML索引,會導致很爛的評估,因為XML索引可以帶統計信息。解決這個問題的方法是在XML列上加上XML索引。

數據類型轉化

如果謂詞數據類型,不對會導致數據類型轉化,這樣也會導致基數評估不准確,是因為列的統計信息無法使用了。

Intra-column比較

Cardinality estimate issues can occur when performing comparisons between columns in the same table. If this is an issue, consider creating computed columns. The computed column can then be referenced in a filter predicate. You can automatically generate the computed column’s associated statistics (by activating automatic statistics creation at the database level) to improve overall estimates. If intra-table column comparison cardinality estimation is a frequent issue, consider normalization techniques (separate tables), derived tables, or common table expressions.

查詢提示

盡量避免使用查詢提示,查詢提示會覆蓋優化器的選擇,對於某些情況可能會導致更爛的性能。

分布式查詢

當通過連接服務器查詢數據的時候,如果沒有權限訪問統計信息的話,會導致查詢性能很爛。

在使用前先確定訪問統計信息需要多大的權限。

遞歸CTE

遞歸CTE也有評估偏差問題,可以看Optimize Recursive CTE Query.

謂詞復雜性

避免在謂詞列上使用函數或者表達式,這個沒啥好說,嚴重影響性能。

查詢復制性

復制的查詢也會讓評估帶來偏差,評估本來就是不准確的,來回怎么倒騰就更加不准確了,應該簡化查詢。

 

參考:

Optimizing Your Query Plans with the SQL Server 2014 Cardinality Estimator


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM