Custering Factorから話します.
2838 ワード
参照のリンク:http://www.cnblogs.com/killkill/archive/2009/10/04/1578054.html
この文章はOracleのCustering Factorから、ORACLEとSQL Serverの二つのデータベースを比較してみました.最初に著者はこの2つのデータベースはこの点でほぼ同じであるべきだと思っていましたが、実際に最後に一つのデータベースの概念を発見しました.あるデータベースで問題があります.別のデータベースで上根本はこの問題がありません.
しかし、ここの著者の結論は正しくないと思います.Custering FactorはORACLEデータベースにおけるデータ格納の乱雑さを反映しています.値が大きいほど、格納されたデータが乱雑になることを説明しています.この乱雑無章はインデックスによってデータにアクセスする時、インデックス記録は大量のデータページに散乱しています.集中した少量のデータページに散乱しているのではありません.
SQL Serverも同じだと思います.SQL ServerはCustering Factorというパラメータがないですが、問題は同じです.
例えば、インデックスが作成されていますが、このインデックスは同じページに保存されています.インデックス値に対応するデータ記録のページが離散的であれば、例えばインデックスの中にリーフページがあり、インデックス記録が100件保存されています.つまり、100件のデータ記録に対応しています.この100件の記録は、100個のデータページに保存される可能性があります.これはSQL Serverに格納されているデータが乱雑であるというわけではなく、インデックス記録からデータ記録までの対応関係が乱雑であり、N本のインデックス記録はいずれも1つまたは少数のデータページにあるというわけではなく、広範囲のデータページに分布しているので、同じように多くのデータを読み取るには、複数の読み取りが必要になるかもしれません.多くの読んだ記録は私達が必要としているのではなくて、すべて照会範囲内のデータではないです.これは記録を読みたいからです.この記録を含むデータページを読みます.
oracleで表を作成する語句:
create table tab 02 as select*from source order by;
SQL Serverで表の文を作成します.
select*into tab 02 from Source order by x;
特に指摘したいのは、SQL Serverのヘルプファイルに書いてあります.SELECT...INTO文と一緒に使用して、他のソースから行を挿入する場合、ORDER BY子文は指定された順番で挿入することが保証されません.
つまり、筆者は並べ替えによって、最後のtab 02テーブルのデータは完全にyフィールドの値によって並べ替えられていると思っていますが、実際にはSQL Serverは指定された順序でこれらの行を挿入することを保証していません.これらの行がtab 02に挿入されると、順序はtab 01と全く同じかもしれません.
次の実験を行います.フィールドzを追加して、tab 02テーブルに対してzフィールドの統合インデックスを構築し、データの保存順序を変更します.つまり、tab 02はxフィールドの順序ではなく、zの値に従って並べ替えます.つまりインデックスからデータ記録までの雑然とした対応関係を作成しました.
create table Source
(
x int ,
y int,
z int
);
begin tran;
declare @n int;
set @n = 0;
while @n < 1000000
begin
insert into source(x,y,z) values ( @n , checksum(newid()),checksum(newid()) );
set @n=@n+1;
end;
commit;
select * into tab01 from Source;
select * into tab02 from Source order by x;
create index idx01 on tab01(x);
-- z
create clustered index idx_tab02 on tab02(z)
create index idx02 on tab02(x);
set statistics io on
/*
idx01, x , x ,
rid, , 10 ,
:
(1 )
'tab01'。 1, 1007 , 0 , 0 ,lob 0 ,lob 0 ,lob 0 。
(1 )
*/
select avg(y/(x+1)) from tab01 where x between 10000 and 11000;
/*
idx02, x , z ,
>=10000 <=11000 1000 , ,
, y , 。
, >=10000 <=11000 1000 ,
1000 , 100 , 108 , 1000 100 ,
。
:
(1 )
'tab02'。 1, 3080 , 0 , 0 ,lob 0 ,lob 0 ,lob 0 。
(1 )
*/
select avg(y/(x+1)) from tab02 where x between 10000 and 11000;