Ich habe mit verschiedenen Entwicklern in meinem Büro eine ständige Debatte über die Kosten eines Index geführt und darüber, ob die Eindeutigkeit vorteilhaft oder kostspielig ist (wahrscheinlich beides). Der Kern des Problems sind unsere konkurrierenden Ressourcen.
Hintergrund
Ich habe zuvor in einer Diskussion gelesen, dass ein Unique
Index keine zusätzlichen Kosten verursacht, da eine Insert
Operation implizit prüft, wo er in den B-Baum passt, und einen Eindeutiger anhängt, wenn ein Duplikat in einem nicht eindeutigen Index gefunden wird das Ende des Schlüssels, fügt aber sonst direkt ein. In dieser Abfolge von Ereignissen entstehen für einen Unique
Index keine zusätzlichen Kosten.
Mein Kollege bekämpft diese Aussage, indem er sagt, dass dies Unique
als zweite Operation nach der Suche nach der neuen Position im B-Baum erzwungen wird und daher in der Pflege teurer ist als ein nicht eindeutiger Index.
Im schlimmsten Fall habe ich Tabellen mit einer Identitätsspalte (von Natur aus eindeutig) gesehen, die der Clustering-Schlüssel der Tabelle ist, aber ausdrücklich als nicht eindeutig angegeben wird. Auf der anderen Seite ist meine Besessenheit von der Eindeutigkeit am schlimmsten, und alle Indizes werden als eindeutig erstellt. Wenn es nicht möglich ist, eine explizit eindeutige Beziehung zu einem Index zu definieren, hänge ich die PK der Tabelle an das Ende des Index an, um sicherzustellen, dass der Index eindeutig ist Einzigartigkeit ist garantiert.
Ich bin häufig an Codeüberprüfungen für das Entwicklerteam beteiligt, und ich muss in der Lage sein, allgemeine Richtlinien zu geben, denen sie folgen können. Ja, jeder Index sollte ausgewertet werden. Wenn Sie jedoch fünf Server mit jeweils Tausenden von Tabellen und bis zu zwanzig Indizes in einer Tabelle haben, müssen Sie in der Lage sein, einige einfache Regeln anzuwenden, um ein bestimmtes Qualitätsniveau sicherzustellen.
Frage
Hat die Einzigartigkeit zusätzliche Kosten im Insert
Vergleich zu den Kosten für die Aufrechterhaltung eines nicht eindeutigen Index? Was ist zweitens falsch daran, den Primärschlüssel einer Tabelle an das Ende eines Indexes anzuhängen, um die Eindeutigkeit sicherzustellen?
Beispiel Tabellendefinition
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);
Beispiel
Ein Beispiel , warum ich das hinzufügen würde Unique
Schlüssel zum Ende eines Index ist in einem unsere Faktentabellen. Es gibt ein Primary Key
, auf dem eine Identity
Spalte. Das Clustered Index
ist jedoch stattdessen die Partitionierungsschema-Spalte, gefolgt von drei Fremdschlüsseldimensionen ohne Eindeutigkeit. Die Leistung bei der Auswahl dieser Tabelle ist miserabel, und ich erhalte häufig bessere Suchzeiten, wenn ich die Primary Key
mit einer Schlüsselsuche verwende, anstatt die zu nutzen Clustered Index
. Andere Tabellen, die ein ähnliches Design aufweisen, jedoch Primary Key
am Ende angehängt sind, weisen eine erheblich bessere Leistung auf.
-- 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
und Weise und dieIf
Strukturen auf 10 Ebenen begrenzt sind, ist es sinnvoll, dass auch die Auflösung nicht eindeutiger Entitäten begrenzt ist. Ihrer Aussage nach scheint dies nur in Fällen zuzutreffen, in denen der Clustering-Schlüssel nicht eindeutig ist. Ist dies ein Problem für einenNonclustered Index
oder liegt der Clustering-Schlüssel vor,Unique
gibt es kein Problem fürNonclustered
Indizes?