0

运行于: SQL Server 2008 R2 Standard。尽管我认为这是所有数据库的问题,而不仅仅是 SQL Server。

背景:我一直听说/读过/被告知,索引的前沿应该是高度选择性的。当您有查询寻找特定值或一小组值时,这是有道理的——产品 ID 或类似的东西。

一般问题:有时高选择性索引有用吗?

例如:我有一个包含 3.5 亿行的表。该表包含一堆价格。该表具有以下列:

  • priceId-- 表上的聚集索引
  • warehouseId-- fk 到 10 个仓库之一,平均分布在150m 行中
  • algorithmId-- fk 到我计算价格的 23 种算法之一,平均分布在 1.5 亿行中
  • priceDate-- 我们上次计算价格的日期
  • productId

然后我运行这个查询:

select productId 
from price 
where warehouseId = 1 
    and algorithmId = 1 
order by priceDate

具体问题:我不会从这样的索引中受益吗?

create nonclustered index ix_p 
on price (warehouseId, algorithmId, priceDate) includes (productId)

看来我会受益 b/c 我已经创建了一个覆盖索引,过滤器列组织得很好,这样 SQL Server 可以一次切出大块并按priceDate. 那有意义吗?它有效吗?

注意:我要试试这个,然后告诉你我发现了什么。

4

2 回答 2

0

简短的回答 - 是的,但你的存储空间基本上翻了一番。

长答案:

我在具有 1.5 亿行数据的 SQL 2012 VirtualBox Server 2008 VM 上对此进行了测试。文件组存储在 VM 映像上,该映像位于与固态驱动器的 USB 3.0 连接上(顺序读取似乎约为 250 mb/s,写入约 150 mb/s)。

我构建了一个带有伪随机日期和产品 ID 的表,其中 1-10 的仓库 ID 均匀分布,1-23 的算法均匀分布。(基本上我在 SSIS 中编写了一个加载数据的源脚本组件)。

表存储空间约为 4.7 GB,主键 priceid 上有一个聚集索引。

运行此查询:

select productId 
from price 
where warehouseId = 1 
    and algorithmId = 1 
order by priceDate

大约 30 秒内返回了大约 100 万行。Plan 表示聚集索引扫描加上排序(按 priceDate 排序)。

然后我添加了这个非聚集索引:

create nonclustered index ix_p 
on price (warehouseId, algorithmId, priceDate) include (productId)

这个索引几乎和表一样大 - 大约 4.3 GB。

添加非聚集索引消除了 priceDate 上的 SORT 步骤,并改为执行非聚集索引查找以访问数据。创建此索引花费了 11 多分钟。

相同的查询:大约 4 秒内返回了大约 100 万行。Plan 表示非聚集索引查找。

我认为这样做的最重要的事情本质上是创建数据的两个副本——一个在聚集索引结构中,一个在“非聚集”结构中。

我预计插入需要大约两倍的时间,因为现在您必须为每个插入创建基本上两行。

您是否定期更新此表?可能还有其他一些策略可能会有所帮助。

于 2013-11-08T19:29:27.783 回答
0

我刚刚完成了一个类似于我在问题中描述的非聚集索引。表有 101,308,183 行,每行 61 个字节。以下是一些结果:

以 productId 和仓库为键的当前“选择性”索引:

  • 返回 461,000 行
  • 平均运行时间:2 分 36 秒
  • 扫描计数:116
  • 逻辑读取:9,870,354
  • 物理读取:20,086
  • 预读:967,324

使用我原来的问题中描述的新的非选择性索引:

  • 返回 461,000 行
  • 平均运行时间:47 秒
  • 扫描次数:76
  • 逻辑读取:109,934
  • 物理读取:0
  • 预读:1

总而言之,非选择性索引使我的逻辑读取减少了 90 倍(987 万到 110k),物理读取减少了 100%(从 20k 到 0),预读减少了 100%(967k 到 0) .

同样,我相信这是因为 SQL 已经对所有数据进行了排序,因此很容易切割(即排除)大块数据。因为索引涵盖了这个查询(这是我们在生产环境中运行的两个查询之一),所以我们不会浪费时间进行键查找。

于 2013-11-12T04:36:12.757 回答