ฉันได้มีการถกเถียงอย่างต่อเนื่องกับนักพัฒนาหลายคนในสำนักงานของฉันเกี่ยวกับค่าใช้จ่ายของดัชนีและความเป็นเอกลักษณ์หรือไม่นั้นมีประโยชน์หรือมีค่าใช้จ่ายสูง (อาจเป็นได้ทั้งสองอย่าง) ปมของปัญหาคือทรัพยากรการแข่งขันของเรา
พื้นหลัง
ก่อนหน้านี้ฉันได้อ่านการสนทนาที่ระบุว่าUnique
ดัชนีนั้นไม่มีค่าใช้จ่ายเพิ่มเติมในการบำรุงรักษาเนื่องจากการInsert
ดำเนินการโดยปริยายจะตรวจสอบว่าตรงกับต้นไม้ B หรือไม่และหากพบซ้ำในดัชนีที่ไม่ซ้ำใคร จุดสิ้นสุดของคีย์ แต่อย่างอื่นแทรกโดยตรง ในลำดับเหตุการณ์นี้Unique
ดัชนีไม่มีค่าใช้จ่ายเพิ่มเติม
ผู้ร่วมงานของฉันต่อสู้กับแถลงการณ์นี้โดยกล่าวว่าการUnique
บังคับใช้เป็นการดำเนินการครั้งที่สองหลังจากการค้นหาตำแหน่งใหม่ในต้นไม้ B และทำให้ค่าใช้จ่ายในการบำรุงรักษาสูงกว่าดัชนีที่ไม่ซ้ำใคร
ที่แย่ที่สุดฉันได้เห็นตารางที่มีคอลัมน์ข้อมูลประจำตัว (ไม่ซ้ำกันโดยเนื้อแท้) นั่นคือคีย์การทำคลัสเตอร์ของตาราง แต่ระบุไว้อย่างชัดเจนว่าไม่ซ้ำกัน ในอีกด้านหนึ่งของความเลวร้ายที่สุดคือการครอบงำจิตใจของฉันด้วยเอกลักษณ์และดัชนีทั้งหมดจะถูกสร้างขึ้นเป็นเอกลักษณ์และเมื่อไม่สามารถกำหนดความสัมพันธ์ที่ไม่ซ้ำกันอย่างชัดเจนกับดัชนีฉันผนวก PK ของตารางไปยังจุดสิ้นสุดของดัชนีเพื่อรับรอง รับประกันความเป็นเอกลักษณ์
ฉันมีส่วนร่วมในการตรวจสอบโค้ดสำหรับทีม dev บ่อยครั้งและฉันต้องสามารถให้แนวทางทั่วไปเพื่อให้พวกเขาทำตาม ใช่ทุกดัชนีควรได้รับการประเมิน แต่เมื่อคุณมีเซิร์ฟเวอร์ห้าตัวที่มีตารางนับพันแต่ละตัวและมากถึงยี่สิบดัชนีในตารางคุณจะต้องสามารถใช้กฎง่าย ๆ เพื่อรับประกันคุณภาพในระดับหนึ่ง
คำถาม
เอกลักษณ์มีค่าใช้จ่ายเพิ่มเติมที่ส่วนท้ายของการInsert
เปรียบเทียบกับค่าใช้จ่ายในการบำรุงรักษาดัชนีที่ไม่ซ้ำหรือไม่? ประการที่สองมีอะไรผิดปกติในการผนวกคีย์หลักของตารางต่อท้ายดัชนีเพื่อให้แน่ใจว่ามีเอกลักษณ์?
ตัวอย่างคำจำกัดความของตาราง
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);
ตัวอย่าง
ตัวอย่างของสาเหตุที่ฉันจะเพิ่มUnique
คีย์ไปยังจุดสิ้นสุดของดัชนีอยู่ในตารางข้อเท็จจริงของเรา มีความเป็นไปPrimary Key
ได้ว่าเป็นIdentity
คอลัมน์ อย่างไรก็ตาม, Clustered Index
แทนที่จะเป็นคอลัมน์ชุดรูปแบบการแบ่ง, ตามด้วยสามคีย์ต่างประเทศที่ไม่มีเอกลักษณ์ เลือกประสิทธิภาพการทำงานบนตารางนี้คือสุดซึ้งและบ่อยครั้งที่ฉันได้รับดีกว่าขอเวลาใช้กับการค้นหาที่สำคัญมากกว่าการใช้ประโยชน์จากPrimary Key
Clustered Index
ตารางอื่น ๆ ที่เป็นไปตามการออกแบบที่คล้ายกัน แต่มีส่วนPrimary Key
ท้ายต่อท้ายมีประสิทธิภาพที่ดีกว่ามาก
-- 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
และIf
โครงสร้างถูก จำกัด ไว้ที่ 10 ระดับมันทำให้รู้สึกว่ายังมีข้อ จำกัด ในการแก้ไขเอนทิตีที่ไม่ซ้ำกัน ตามคำสั่งของคุณฟังดูเหมือนว่าจะมีผลเฉพาะกับกรณีที่คีย์การทำคลัสเตอร์ไม่ซ้ำกัน นี่เป็นปัญหาสำหรับ aNonclustered Index
หรือถ้าคีย์การทำคลัสเตอร์Unique
ไม่มีปัญหาสำหรับNonclustered
ดัชนีหรือไม่?