【问题标题】:SQL Server range indexing ideasSQL Server 范围索引思想
【发布时间】:2014-10-25 09:28:34
【问题描述】:

我需要帮助了解如何在表上创建适当的索引以进行快速范围选择。

我有一个包含以下列的表格:

--- 类型


frameidx --- int

u --- int

v --- int

x --- 浮点数(53)

y --- 浮点数(53)

z --- 浮点数(53)


这些列都不是唯一的。

此表中大约有 3000 万条记录。

一般的查询应该是这样的:

   Select x, y, z from tablename
   Where
       frameidx = 4 AND
       u between 34 AND 500
       v between 0 AND 200

非常简单,没有连接,没有嵌套的东西。只是很好的子集选择。

例如,我应该在 MS SQL Server (2012) 中为此表执行哪种索引,以便能够在(理想情况下)不到 100 毫秒的时间内获取记录(可能来自此查询的数千条记录) ?

谢谢。

【问题讨论】:

  • 假设您总是过滤 frameidxuv 我认为 3 列上的复合索引,xyz 作为非键列将是最通用的:CREATE NONCLUSTERED INDEX IX_tablename__frameidx_u_v ON tablename INCLUDE (x, y, z); - 但是,我认为期望优化所有范围的查询以在不到 100 毫秒的时间内从具有 30m 行的表中返回数千行有点乐观。

标签: sql sql-server indexing sql-server-2012


【解决方案1】:

如果您没有索引,SQL Server 需要扫描整个表以查找所需的数据。对于这么大的表(30M 行),这很耗时。

如果您有适合您的查询的索引,SQL 服务器将寻找它们(即,它将使用索引结构在索引中快速找到所需的行)。索引由给定索引顺序的索引列值和指向索引表中的行的指针组成,因此一旦在索引中找到数据,就可以使用这些指针从索引表中恢复必要的数据。

所以,如果您想加快速度,您需要为要用于过滤范围的列创建索引。

添加索引会提高查询响应时间,但也会占用更多空间,并使插入速度变慢。所以你不应该创建很多索引。

如果您要一直使用所有列进行过滤,您应该只创建一个索引。而且,理想情况下,该索引应该更具选择性,即具有最多不同值(重复值最少)的索引。每个查询只能使用一个索引。

如果您要使用不同的范围过滤器集,您应该创建更多索引。

使用复合材料有好有坏。在复合键中,行按索引中的所有列排序。因此,如果您按 A、B、C 和 D 进行索引,则按 A 过滤或排序将给出索引的连续行,这是一个快速操作。并且按 A、B、C 和 D 过滤是该索引的理想选择。但是,仅按 D 过滤或排序是此索引的最坏情况,因为它需要恢复遍布整个索引的数据:请记住,数据按 A、B、C、D 排序,所以D 信息遍布整个索引。根据几个因素(表统计信息、索引选择性等),甚至可能根本没有使用索引,而是扫描了表。

关于聚集索引的最后一点说明:聚集索引定义了数据在表中存储的物理顺序。 It doesn't need to be unique。如果您在大多数情况下使用其中一列进行过滤,则最好将其设为表的聚集索引,因为在这种情况下,不是使用指针查找索引并在索引表中查找数据,直接查找该表,这可以提高性能。

所以没有简单的答案,但我希望知道你有信息来提高你的查询速度。

编辑

根据一条非常有趣的评论,更正了信息。

【讨论】:

  • 原谅我厚,我还在学习。所以我应该添加一个自动生成的主键列,即使该列从来不是查询的一部分?此外,应该注意的是空间和插入时间根本不是问题,因为数据库将“离线”准备好,然后仅选择查询“在线”。因此,考虑到这一点,我是否应该在列 frameidx、u 和 v 上创建单个复合索引?
  • “首先你应该为表添加一个主键,以便它可以被正确索引” - 这根本不是真的!首先,我假设您的意思是聚集索引而不是主键,其次heap tables 将在没有聚集索引的情况下使用有效的行指针,并且通常在始终通过非聚集索引访问数据时使用,因此聚集索引是 不需要正确索引。
  • @GarethD 哇,你指出的太好了!我不知道 RID。而且我不知不觉地认为聚集索引应该是唯一的(我不想使答案复杂化,所以我对 PK 进行了讨论)。感谢您的评论,现在我看到聚集索引可以是非唯一的,此外还可以使用堆的 RID 进行索引而不需要唯一的 PK。
  • +1 用于编辑,索引问题几乎不可能回答这种模糊的问题,通常可以实现的最好的方法是解释索引是如何工作的,并希望这足以让 OP 开始,这正是你所做的。
  • 感谢两位的帮助。我学到了很多关于集群/非集群索引的知识,最终通过执行计划分析器的反复试验,了解到我需要在 frameidx、u 和 v 列上使用非集群索引,该列包含在剩余的 x 上, y 和 z 列(就像 GaraethD 在 cmets 中提供的一样) 服务器现在在大约 101 毫秒内返回约 54,000 行。非常好,正好可以找到我正在寻找的东西。非常感谢你们。真的很感激。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-06-01
  • 2010-12-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-10-01
  • 1970-01-01
相关资源
最近更新 更多