Sql-Server
缺失索引創建建議
我一直在使用 sp_blitzindex,它非常有幫助(感謝 Brent Ozar 和團隊)。我對我的數據庫執行了這個過程,下面是一個屬於 Indexaphobia 組的表的發現:
下面是基礎表的定義:
CREATE TABLE [dbo].[table_name]( [L] [int] IDENTITY(1,1) NOT NULL, [R] [varchar](15) NOT NULL, [A] [int] NOT NULL, [VAR32_01] [varchar](32) NULL, [VAR32_02] [varchar](32) NULL, [VAR32_03] [varchar](32) NULL, [VAR32_04] [varchar](32) NULL, [VAR32_05] [varchar](32) NULL, [VAR32_06] [varchar](32) NULL, [VAR32_07] [varchar](32) NULL, [VAR32_08] [varchar](32) NULL, [VAR32_09] [varchar](32) NULL, [VAR32_10] [varchar](32) NULL, [VAR32_11] [varchar](32) NULL, [VAR32_12] [varchar](32) NULL, [VAR32_13] [varchar](32) NULL, [VAR32_14] [varchar](32) NULL, [VAR32_15] [varchar](32) NULL, [VAR32_16] [varchar](32) NULL, [VAR32_17] [varchar](32) NULL, [VAR32_18] [varchar](32) NULL, [VAR32_19] [varchar](32) NULL, [VAR32_20] [varchar](32) NULL, [VAR32_21] [varchar](32) NULL, [VAR32_22] [varchar](32) NULL, [VAR32_23] [varchar](32) NULL, [VAR32_24] [varchar](32) NULL, [VAR32_25] [varchar](32) NULL, [VAR32_26] [varchar](32) NULL, [VAR32_27] [varchar](32) NULL, [VAR32_28] [varchar](32) NULL, [VAR32_29] [varchar](32) NULL, [VAR32_30] [varchar](32) NULL, [VAR32_31] [varchar](32) NULL, [VAR32_32] [varchar](32) NULL, [VAR32_33] [varchar](32) NULL, [VAR32_34] [varchar](32) NULL, [VAR32_35] [varchar](32) NULL, [VAR32_36] [varchar](32) NULL, [VAR32_37] [varchar](32) NULL, [VAR32_38] [varchar](32) NULL, [VAR32_39] [varchar](32) NULL, [VAR32_40] [varchar](32) NULL, [VAR32_41] [varchar](32) NULL, [VAR32_42] [varchar](32) NULL, [VAR32_43] [varchar](32) NULL, [VAR32_44] [varchar](32) NULL, [VAR32_45] [varchar](32) NULL, [VAR32_46] [varchar](32) NULL, [VAR32_47] [varchar](32) NULL, [VAR32_48] [varchar](32) NULL, [VAR32_49] [varchar](32) NULL, [VAR32_50] [varchar](32) NULL, [VAR32_51] [varchar](32) NULL, [VAR32_52] [varchar](32) NULL, [VAR32_53] [varchar](32) NULL, [VAR32_54] [varchar](32) NULL, [VAR32_55] [varchar](32) NULL, [VAR32_56] [varchar](32) NULL, [VAR32_57] [varchar](32) NULL, [VAR32_58] [varchar](32) NULL, [VAR32_59] [varchar](32) NULL, [VAR32_60] [varchar](32) NULL, [VAR32_61] [varchar](32) NULL, [VAR32_62] [varchar](32) NULL, [VAR32_63] [varchar](32) NULL, [VAR32_64] [varchar](32) NULL, [VAR64_01] [varchar](64) NULL, [VAR64_02] [varchar](64) NULL, [VAR64_03] [varchar](64) NULL, [VAR64_04] [varchar](64) NULL, [VAR64_05] [varchar](64) NULL, [VAR64_06] [varchar](64) NULL, [VAR64_07] [varchar](64) NULL, [VAR64_08] [varchar](64) NULL, [VAR64_09] [varchar](64) NULL, [VAR64_10] [varchar](64) NULL, [VAR64_11] [varchar](64) NULL, [VAR64_12] [varchar](64) NULL, [VAR64_13] [varchar](64) NULL, [VAR64_14] [varchar](64) NULL, [VAR64_15] [varchar](64) NULL, [VAR64_16] [varchar](64) NULL, [VAR64_17] [varchar](64) NULL, [VAR64_18] [varchar](64) NULL, [VAR64_19] [varchar](64) NULL, [VAR64_20] [varchar](64) NULL, [VAR64_21] [varchar](64) NULL, [VAR64_22] [varchar](64) NULL, [VAR64_23] [varchar](64) NULL, [VAR64_24] [varchar](64) NULL, [VAR64_25] [varchar](64) NULL, [VAR64_26] [varchar](64) NULL, [VAR64_27] [varchar](64) NULL, [VAR64_28] [varchar](64) NULL, [VAR64_29] [varchar](64) NULL, [VAR64_30] [varchar](64) NULL, [VAR64_31] [varchar](64) NULL, [VAR64_32] [varchar](64) NULL, [VAR128_01] [varchar](128) NULL, [VAR128_02] [varchar](128) NULL, [VAR128_03] [varchar](128) NULL, [VAR128_04] [varchar](128) NULL, [VAR128_05] [varchar](128) NULL, [VAR128_06] [varchar](128) NULL, [VAR128_07] [varchar](128) NULL, [VAR128_08] [varchar](128) NULL, [VAR128_09] [varchar](128) NULL, [VAR128_10] [varchar](128) NULL, [VAR128_11] [varchar](128) NULL, [VAR128_12] [varchar](128) NULL, [VAR128_13] [varchar](128) NULL, [VAR128_14] [varchar](128) NULL, [VAR128_15] [varchar](128) NULL, [VAR128_16] [varchar](128) NULL, [VAR256_01] [varchar](256) NULL, [VAR256_02] [varchar](256) NULL, [VAR256_03] [varchar](256) NULL, [VAR256_04] [varchar](256) NULL, [VAR256_05] [varchar](256) NULL, [VAR256_06] [varchar](256) NULL, [VAR256_07] [varchar](256) NULL, [VAR256_08] [varchar](256) NULL, [VAR512_01] [varchar](512) NULL, [VAR512_02] [varchar](512) NULL, [VAR512_03] [varchar](512) NULL, [VAR512_04] [varchar](512) NULL, [VAR1024_01] [varchar](1024) NULL, [VAR1024_02] [varchar](1024) NULL, [E] [varchar](20) NULL, [M] [varchar](40) NULL, [E] [varchar](50) NULL, [N] [varchar](40) NULL, [TN] [int] NULL, [T] [numeric](1, 0) NULL, [D] [numeric](1, 0) NULL, CONSTRAINT [XPKtable_name] PRIMARY KEY NONCLUSTERED ( [L] ASC, [R] ASC )
根據這些缺少的索引詳細資訊,我計劃創建具有以下定義的索引:
create nonclustered index table_name_incl(A,VAR32_02) include(L,R,E,T,D,VAR32_10,VAR32_18,VAR32_19,VAR32_20,VAR64_11,VAR64_02,VAR32_42,VAR32_39,VAR32_38,VAR32_35,VAR32_39,VAR32_24,VAR32_25,VAR32_27)
我根據所有 6 個缺失索引統計資訊中這些列的出現次數得出了上述列。
從表定義中可以看出,這是一個堆,並且在該表上沒有聚集索引。
感謝您對此的指導或任何幫助。
Version: Microsoft SQL Server 2014 (SP3) (KB4022619) - 12.0.6024.0 (X64) Sep 7 2018 01:37:51 Enterprise Edition: Core-based Licensing (64-bit) on Windows NT 6.3 (Build 9600: ) (Hypervisor)
來自評論
聚集索引會帶來許多約束,如空值、重複等,而非聚集索引不會給供應商帶來任何風險,而且他們很容易就達成一致。
這不是真的,聚集索引不允許重複、NULL 甚至重複 NULL,除非它們被聲明為 UNIQUE。
這些插入都會成功:
DROP TABLE IF EXISTS dbo.t; CREATE TABLE dbo.t ( id INT NULL ); CREATE CLUSTERED INDEX c ON dbo.t ( id ); INSERT dbo.t ( id ) VALUES ( 1 ); INSERT dbo.t ( id ) VALUES ( 1 ); INSERT dbo.t ( id ) VALUES ( 1 ); INSERT dbo.t ( id ) VALUES ( NULL ); INSERT dbo.t ( id ) VALUES ( NULL ); INSERT dbo.t ( id ) VALUES ( NULL ); SELECT * FROM dbo.t AS t;
這些插入將在第一個唯一值之後失敗:
DROP TABLE IF EXISTS dbo.t; CREATE TABLE dbo.t ( id INT NULL ); CREATE UNIQUE CLUSTERED INDEX c ON dbo.t ( id ); INSERT dbo.t ( id ) VALUES ( 1 ); INSERT dbo.t ( id ) VALUES ( 1 ); INSERT dbo.t ( id ) VALUES ( 1 ); INSERT dbo.t ( id ) VALUES ( NULL ); INSERT dbo.t ( id ) VALUES ( NULL ); INSERT dbo.t ( id ) VALUES ( NULL ); SELECT * FROM dbo.t AS t;
您的建議起到了作用,我在測試環境中的 A 列上創建了聚集索引,到目前為止根本沒有抱怨缺少索引,只是補充說測試中也缺少索引抱怨。在與供應商確認後,我們將很快將此更改推廣到生產。非常感謝。
👍👍👍