我知道这可能是一个棘手的问题,而且它在很大程度上取决于背景。
我有一个包含大约1000万行的表的数据库(每行包含4个varchar)。 字段上有一个非聚集的索引(varchar)用于where。
我有点困惑,因为在使用索引列上的where选择一行时,大约需要一秒钟才能结束。
任何改善此响应时间的建议? 索引聚类会在这里成为一个好的解决方案吗?
以下是表格定义:
CREATE TABLE [dbo].[MYTABLE](
[ID] [uniqueidentifier] NOT NULL DEFAULT (newid()),
[CreationDate] [datetime] NOT NULL DEFAULT (getdate()),
[UpdateDate] [datetime] NULL,
[FIELD1] [varchar](9) NOT NULL,
[FIELD2] [varchar](max) NOT NULL,
[FIELD3] [varchar](1) NULL,
[FIELD4] [varchar](4) NOT NULL,
CONSTRAINT [PK_MYTABLE] PRIMARY KEY CLUSTERED
(
[ID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
这是索引定义:
CREATE UNIQUE NONCLUSTERED INDEX [IX_FIELD1] ON [dbo].[MYTABLE]
(
[FIELD1] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON)
这是我使用的查询(非常基本):
SELECT * FROM MYTABLE WHERE FIELD1 = 'DATA'
答案 0 :(得分:1)
如果您确定WHERE
子句中使用的列是唯一的,则可以在该列上创建UNIQUE CLUSTERED INDEX。
如果该列中的值不唯一,则可以实施COVERING INDEXES。例如,如果您有此索引:
CREATE NONCLUSTERED INDEX IX_Column4 ON MyTable(Column4)
INCLUDE (Column1, Column2);
执行以下查询时:
SELECT Column1, Column2 FROM MyTable WHERE Column4 LIKE 'Something';
您(很可能)正在使用IX_Column4
索引。但在执行类似的事情时:
SELECT Column1, Column2, Column3 FROM MyTable WHERE Column4 LIKE 'Something';
您不会受益于此类指数所提供的优势。
如果您的表格中的行是INSERTED, DELETED or UPDATED
,那么您应该检查INDEX FRAGMENTATION and REBUILD or REORGANIZE这些行。
如果您想了解有关索引的更多信息,我会推荐以下文章:
希望它有所帮助。
答案 1 :(得分:1)
对于这种情况,由于您选择了所有列(*
),因此将非聚簇索引更改为聚簇索引将增加时间,因为访问其他列(索引中未包含的列,未按顺序排列,也未按顺序排列)来自非聚集索引的INCLUDE
)将需要检索具有实际数据的另一页面。
由于您不能按表格拥有多于1个聚簇索引,因此您必须删除现有索引(在这种情况下为PRIMARY KEY
)并在之后创建它。
ALTER TABLE dbo.MYTABLE DROP [PK_MYTABLE] -- This might fail if you have foreign keys
ALTER TABLE dbo.MYTABLE ADD CONSTRAINT PK_MYTABLE PRIMARY KEY NONCLUSTERED (ID)
DROP INDEX [IX_FIELD1] ON [dbo].[MYTABLE]
CREATE CLUSTERED INDEX [IX_FIELD1] ON [dbo].[MYTABLE] (FIELD1)
索引访问时间也可能因其碎片而有很大差异(如果您有许多插入,删除或更新的值不大于或低于上一个/第一个)。
另请注意,如果您正在执行其他操作,如连接,函数调用或其他WHERE
过滤器,则引用可能决定不使用索引。