0

在下面的查询(查询从 c# 应用程序运行)中给出长时间的 DateTime 时,我遇到了超时问题。表有 3000 万行,在 ID(不是主键)上有一个非聚集索引。

发现没有主键,所以我最近将 ID 更新为主键,现在它没有给我超时。谁能帮我在下面的查询中为将来创建多个键的索引,以及如果我从该表中删除非聚集索引并在多个列上创建索引?数据增长迅速,性能需要改进

select 
ID, ReferenceNo, MinNo, DateTime, DataNo from tbl1
where 
DateTime BETWEEN '04/09/2013' AND '20/11/2013'
and  ReferenceNo = 4 and MinNo = 3 and DataNo = 14 Order by ID

这是创建脚本

CREATE TABLE [dbo].[tbl1](  [ID] [int] IDENTITY(1,1) not null,  [ReferenceNo] [int] not null,   [MinNo] [int] not null,     [DateTime] [datetime] not null,     [DataNo] [int] not null,  CONSTRAINT [tbl1_pk] 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]
4

2 回答 2

1

如果不了解更多关于您的数据库及其使用方式的信息,很难判断您应该使用哪个索引。

您可能希望将 ID 列更改为聚集索引。如果 ID 是一个标识列,则在插入新数据时您将获得很少的页面拆分。但是,它需要您重建表,这可能是一个问题,具体取决于您对数据库的使用。您将看到一些停机时间。

如果你想要一个覆盖索引,它应该看起来像这样:

CREATE NONCLUSTERED INDEX [MyCoveringIndex] ON tbl1
(
    [ReferenceNo] ASC,
    [MinNo] ASC,
    [DataNo] ASC,
    [DateTime ] ASC
)

它不需要将 ID 作为列包含,因为它已经在聚集索引中(聚集索引列将包含在所有其他索引中)。但是,这将占用大量空间(如果上面的列是 int 和 datetime 类型,则在 1GB 范围内)。它还会在(大多数情况下)以负面的方式影响您在表上的插入、更新和删除性能。

如果您使用的是 SQL server 的 Enterprice 版,则可以在线模式创建索引。在所有其他情况下,在创建索引时都会对表进行锁定。

也很难知道对表进行了哪些其他查询。您可能希望调整索引中列的顺序以更好地匹配其他查询。

于 2013-11-21T10:41:19.053 回答
0

索引所有字段将是最快的,但可能会浪费大量空间。我猜日期索引将以最少的存储容量成本提供最大的好处,因为数据可能在很长一段时间内均匀分布。如果 MIN() MAX() 日期很接近,那么这将不会有效:

CREATE NONCLUSTERED INDEX [IDX_1] ON [dbo].[tbl1] (
    [DateTime] ASC
)
GO

作为旁注,您可以使用 SSMSE 的“显示估计执行计划”,它将向您展示数据库需要做什么来获取您的数据。它将建议缺少的索引,并提供 CREATE INDEX 语句。这些建议可能非常浪费,但它们会让您了解什么需要这么长时间。此选项位于标准工具栏中,“执行”右侧的四个图标。

于 2013-11-22T14:13:59.603 回答