Tôi đã có một cuộc tranh luận đang diễn ra với các nhà phát triển khác nhau trong văn phòng của tôi về chi phí của một chỉ mục, và liệu tính duy nhất có lợi hay tốn kém (có thể là cả hai). Mấu chốt của vấn đề là nguồn lực cạnh tranh của chúng tôi.
Lý lịch
Trước đây tôi đã đọc một cuộc thảo luận nói rằng một Unique
chỉ mục không phải trả thêm chi phí để duy trì, vì một Insert
hoạt động hoàn toàn kiểm tra xem nó phù hợp với cây B nào và, nếu tìm thấy một bản sao trong một chỉ mục không duy nhất, hãy thêm một chỉ thị vào cuối khóa, nhưng nếu không thì chèn trực tiếp. Trong chuỗi sự kiện này, một Unique
chỉ mục không có chi phí bổ sung.
Đồng nghiệp của tôi chống lại tuyên bố này bằng cách nói rằng nó Unique
được thi hành như một hoạt động thứ hai sau khi tìm kiếm vị trí mới trong cây B, và do đó tốn kém hơn để duy trì hơn một chỉ số không duy nhất.
Tệ nhất, tôi đã thấy các bảng có một cột định danh (vốn là duy nhất) là khóa phân cụm của bảng, nhưng được tuyên bố rõ ràng là không duy nhất. Mặt khác, điều tồi tệ nhất là nỗi ám ảnh của tôi về tính độc đáo và tất cả các chỉ mục được tạo là duy nhất và khi không thể xác định mối quan hệ duy nhất rõ ràng với một chỉ mục, tôi nối PK của bảng vào cuối chỉ mục để đảm bảo tính độc đáo được đảm bảo.
Tôi thường xuyên tham gia vào các đánh giá mã cho nhóm nhà phát triển và tôi cần có thể đưa ra các hướng dẫn chung để họ tuân theo. Đúng, mọi chỉ số đều được đánh giá, nhưng khi bạn có năm máy chủ với hàng nghìn bảng mỗi bảng và có tới hai mươi chỉ mục trên một bảng, bạn cần có thể áp dụng một số quy tắc đơn giản để đảm bảo mức chất lượng nhất định.
Câu hỏi
Liệu tính duy nhất có một chi phí bổ sung ở mặt sau Insert
so với chi phí duy trì một chỉ số không duy nhất? Thứ hai, có gì sai khi gắn thêm Khóa chính của bảng vào cuối chỉ mục để đảm bảo tính duy nhất?
Định nghĩa bảng ví dụ
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);
Thí dụ
Một ví dụ về lý do tại sao tôi sẽ thêm Unique
khóa vào cuối chỉ mục là trong một trong các bảng thực tế của chúng tôi. Có một Primary Key
cái đó là một Identity
cột. Tuy nhiên, Clustered Index
thay vào đó là cột lược đồ phân vùng, theo sau là ba kích thước khóa ngoài không có tính duy nhất. Chọn hiệu suất trên bảng này là rất nhiều và tôi thường nhận được thời gian tìm kiếm tốt hơn bằng cách sử dụng Primary Key
với tra cứu chính thay vì tận dụng Clustered Index
. Các bảng khác theo một thiết kế tương tự, nhưng có phần cuối được Primary Key
thêm vào có hiệu suất tốt hơn đáng kể.
-- 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
vàIf
cấu trúc được giới hạn ở 10 cấp độ, điều đó có ý nghĩa rằng cũng có giới hạn để giải quyết các thực thể không duy nhất. Theo tuyên bố của bạn, điều này nghe có vẻ như chỉ áp dụng cho các trường hợp khi khóa phân cụm không phải là duy nhất. Đây có phải là vấn đề đối với mộtNonclustered Index
hoặc nếu khóa phân cụmUnique
thì không có vấn đề gì đối vớiNonclustered
các chỉ mục?