14

以下のリンクでフィルタリングされた統計を調べていました。

http://blogs.msdn.com/b/psssql/archive/2010/09/28/case-of-using-filtered-statistics.aspx

データは大きく歪んでおり、1 つのリージョンの行が 0 で、残りはすべて異なるリージョンからのものです。以下は、問題を再現するためのコード全体です

create table Region(id int, name nvarchar(100)) 
go 
create table Sales(id int, detail int) 
go 
create clustered index d1 on Region(id) 
go 
create index ix_Region_name on Region(name) 
go 
create statistics ix_Region_id_name on Region(id, name) 
go 
create clustered index ix_Sales_id_detail on Sales(id, detail) 
go

-- only two values in this table as lookup or dim table 
insert Region values(0, 'Dallas') 
insert Region values(1, 'New York') 
go

set nocount on 
-- Sales is skewed 
insert Sales values(0, 0) 
declare @i int 
set @i = 1 
while @i <= 1000 begin 
insert Sales  values (1, @i) 
set @i = @i + 1 
end 
go

update statistics Region with fullscan 
update statistics Sales with fullscan 
go

set statistics profile on 
go 
--note that this query will over estimate 
-- it estimate there will be 500.5 rows 
select detail from Region join Sales on Region.id = Sales.id where name='Dallas' option (recompile) 
--this query will under estimate 
-- this query will also estimate 500.5 rows in fact 1000 rows returned 
select detail from Region join Sales on Region.id = Sales.id where name='New York' option (recompile) 
go

set statistics profile off 
go

create statistics Region_stats_id on Region (id) 
where name = 'Dallas' 
go 
create statistics  Region_stats_id2 on Region (id) 
where name = 'New York' 
go

set statistics profile on 
go 
--now the estimate becomes accurate (1 row) because 
select detail from Region join Sales on Region.id = Sales.id where name='Dallas' option (recompile)

--the estimate becomes accurate (1000 rows) because stats Region_stats_id2 is used to evaluate 
select detail from Region join Sales on Region.id = Sales.id where name='New York' option (recompile) 
go

set statistics profile off

私の質問は、両方のテーブルで以下の統計が利用可能であることです

sp_helpstats 'region','all'
sp_helpstats 'sales','all'

テーブル領域:

statistics_name   statistics_keys
d1                    id
ix_Region_id_name     id, name
ix_Region_name        name

テーブル販売:

statistics_name    statistics_keys
ix_Sales_id_detail     id, detail

1.以下のクエリで見積もりがうまくいかなかった理由

select detail from Region join Sales on Region.id = Sales.id where name='Dallas' option (recompile)

--the estimate becomes accurate (1000 rows) because stats Region_stats_id2 is used to evaluate 
select detail from Region join Sales on Region.id = Sales.id where name='New York' option (recompile) 

2.著者ごとにフィルター処理された統計を作成したとき、見積もりを正しく表示できましたが、フィルター処理された統計を作成する必要があるのはなぜですか。単純な統計を作成した場合でも、同じ結果が得られたので、クエリにフィルター処理された統計が必要であるとどのように言えますか.

これまでに出くわした最高の
もの

しかし、フィルタリングされた統計がここで違いを生んだ理由をまだ理解できていません

前もって感謝します。 更新:7/4

マーティンとジェームズが答えた後に質問を言い換えると:


1.kimberelyスクリプト以外 にデータの歪みを回避する方法はありますか?推定するもう 1 つの方法は、値の行数をカウントすることです。

2.経験上、データの歪みに関する問題に直面したことがありますか?私はそれが大きなテーブルに依存していると思います.しかし、私はいくつかの詳細な回答を探しています.

3. SQL がテーブルをスキャンするための IO コストを取得する必要があります。また、統計情報の更新をトリガーするときに発生するクエリに対して、いくつかのブロッキングが発生することもあります。

理由は、DTA 入力にも基づくいくつかの条件に基づいて、フィルター処理された統計を作成することを考えているからです。

再度、感謝します

4

1 に答える 1

5

これが起こる理由だと思います。SQL Server には、どの ID がどのリージョンに関連する ID であるかを示す統計がないため、同じ見積もり (500.5) 行が得られます。統計 ix_Region_id_name には両方のフィールドがありますが、ヒストグラムは最初の列のみに存在するため、Sales テーブルに含まれる行数に関する見積もりには実際には役立ちません。

を実行するdbcc show_statistics ('Region','ix_Region_id_name')と、結果は次のようになります。

RANGE_HI_KEY   RANGE_ROWS   EQ_ROWS   DISTINCT_RANGE_ROWS   AVG_RANGE_ROWS
0              0            1         0                     1
1              0            1         0                     1

これは、ID ごとに 1 つの行があることを示していますが、名前へのリンクはありません。

ただし、統計 Region_stats_id (ダラス用) を作成すると、次のdbcc show_statistics ('Region','Region_stats_id')ように表示されます。

RANGE_HI_KEY   RANGE_ROWS   EQ_ROWS   DISTINCT_RANGE_ROWS   AVG_RANGE_ROWS
0              0            1         0                     1

そのため、SQL Server は行が 1 つしかないことを認識しており、その ID は 0 です。

同様に Region_stats_id2:

RANGE_HI_KEY   RANGE_ROWS   EQ_ROWS   DISTINCT_RANGE_ROWS   AVG_RANGE_ROWS
1              0            1         0                     1

また、ix_Sales_id_detail の sales の行数は、ID ごとの行を決定するのに役立ちます。

RANGE_HI_KEY   RANGE_ROWS   EQ_ROWS   DISTINCT_RANGE_ROWS   AVG_RANGE_ROWS
0              0            1         0                     1
1              0            1000      0                     1

情報: これは、@MartijnPieters によって削除された回答のコピーです。これは、私が回答するつもりだった質問であるためです。削除された回答に対して何もできないようです。誤って、今日の TheGameiswar の他の統計の質問に最初にこれを書きましたが、既に自分自身を削除しました。

于 2015-06-28T18:01:41.873 に答える