Ofisimdeki çeşitli geliştiricilerle bir endeksin maliyeti hakkında ve benzersizliğin yararlı mı yoksa maliyetli mi (muhtemelen her ikisi de) olup olmadığı konusunda sürekli bir tartışma yaşıyorum. Sorunun en önemli noktası rakip kaynaklarımızdır.
Arka fon
Daha önce Unique
bir Insert
işlemin B ağacına sığdığı yeri dolaylı olarak kontrol ettiğinden ve benzersiz olmayan bir dizinde bir yinelenen bulunursa, anahtarın sonuna, ancak doğrudan doğruya takılır. Bu olay dizisinde, bir Unique
dizinin ek maliyeti yoktur.
İş arkadaşım, bu açıklamada Unique
, B ağacındaki yeni pozisyon arayışından sonra ikinci bir operasyon olarak uygulandığını ve dolayısıyla benzersiz olmayan bir endekse kıyasla daha maliyetli olduğunu söyleyerek mücadele ediyor .
En kötüsü, tablonun kümeleme anahtarı olan, ancak açıkça benzersiz olmayan olarak belirtilen bir kimlik sütunu (doğası gereği benzersiz) olan tablolar gördüm. En kötünün diğer tarafında ise benzersizliğe olan takıntımdır ve tüm dizinler benzersiz olarak oluşturulur ve bir dizinle açıkça benzersiz bir ilişki tanımlamak mümkün olmadığında, sağlamak için tablonun PK'sini dizinin sonuna eklerim teklik garanti edilir.
Sıklıkla dev ekibinin kod incelemelerine katılıyorum ve takip etmeleri için genel yönergeler verebilmeliyim. Evet, her dizin değerlendirilmelidir, ancak her birinde binlerce tablo bulunan beş sunucunuz ve bir tabloda yirmi kadar dizin varsa, belirli bir kalite düzeyi sağlamak için bazı basit kurallar uygulayabilmeniz gerekir.
Soru
Insert
Benzersizliğin, benzersiz olmayan bir dizini sürdürme maliyetine kıyasla ek bir maliyeti var mı ? İkincisi, benzersizliği sağlamak için tablonun Birincil Anahtarını bir dizinin sonuna eklemekle ilgili sorun nedir?
Örnek Tablo Tanımı
create table #test_index
(
id int not null identity(1, 1),
dt datetime not null default(current_timestamp),
val varchar(100) not null,
is_deleted bit not null default(0),
primary key nonclustered(id desc),
unique clustered(dt desc, id desc)
);
create index
[nonunique_nonclustered_example]
on #test_index
(is_deleted)
include
(val);
create unique index
[unique_nonclustered_example]
on #test_index
(is_deleted, dt desc, id desc)
include
(val);
Misal
Neden Unique
bir dizin sonuna anahtar eklemek istiyorum bir örnek bizim olgu tablolarından biridir. Bir yoktur Primary Key
bir olduğunu Identity
sütunu. Ancak, Clustered Index
bunun yerine bölümleme şeması sütunu, ardından benzersiz olmayan üç yabancı anahtar boyutu gelir. Bu tablodaki performans abysmal seçin ve sık sık kullanarak Primary Key
bir anahtar arama ile kullanarak daha iyi arama süreleri elde Clustered Index
. Benzer bir tasarımı takip eden, ancak Primary Key
sonuna kadar eklenen diğer tablolar önemli ölçüde daha iyi performansa sahiptir.
-- date_int is equivalent to convert(int, convert(varchar, current_timestamp, 112))
if not exists(select * from sys.partition_functions where [name] = N'pf_date_int')
create partition function
pf_date_int (int)
as range right for values
(19000101, 20180101, 20180401, 20180701, 20181001, 20190101, 20190401, 20190701);
go
if not exists(select * from sys.partition_schemes where [name] = N'ps_date_int')
create partition scheme
ps_date_int
as partition
pf_date_int all
to
([PRIMARY]);
go
if not exists(select * from sys.objects where [object_id] = OBJECT_ID(N'dbo.bad_fact_table'))
create table dbo.bad_fact_table
(
id int not null, -- Identity implemented elsewhere, and CDC populates
date_int int not null,
dt date not null,
group_id int not null,
group_entity_id int not null, -- member of group
fk_id int not null,
-- tons of other columns
primary key nonclustered(id, date_int),
index [ci_bad_fact_table] clustered (date_int, group_id, group_entity_id, fk_id)
)
on ps_date_int(date_int);
go
if not exists(select * from sys.objects where [object_id] = OBJECT_ID(N'dbo.better_fact_table'))
create table dbo.better_fact_table
(
id int not null, -- Identity implemented elsewhere, and CDC populates
date_int int not null,
dt date not null,
group_id int not null,
group_entity_id int not null, -- member of group
-- tons of other columns
primary key nonclustered(id, date_int),
index [ci_better_fact_table] clustered(date_int, group_id, group_entity_id, id)
)
on ps_date_int(date_int);
go
Case
ve nasılIf
10 seviye ile sınırlı olduğu gibi, benzersiz olmayan varlıkların çözülmesinin de bir sınırı olduğu mantıklıdır. İfadenize göre bu, yalnızca kümeleme anahtarının benzersiz olmadığı durumlar için geçerliymiş gibi görünür. Bu bir sorun mu,Nonclustered Index
yoksa kümeleme anahtarı ise dizinlerUnique
için sorun olmazNonclustered
mı?