为什么没有使用columnstore索引

时间:2017-05-11 12:07:34

标签: sql-server indexing query-performance sql-server-2016 columnstore

我在SQL Server 2016 Enterprise Edition上的40m记录非内存优化表的所有列上都有一个非聚集列存储索引。

强制使用columnstore索引的查询将执行得更快,但优化器继续选择使用聚簇索引和其他非聚簇索引。我有很多可用的RAM,并且正在对维度模型使用适当的查询。

为什么优化器不会选择columnstoreindex?我怎样才能鼓励它的使用(不使用提示)?

以下是不使用columnstore的示例查询:

SELECT
  COUNT(*),
  SUM(TradeTurnover),
  SUM(TradeVolume)
FROM DWH.FactEquityTrade e
--with (INDEX(FactEquityTradeNonClusteredColumnStoreIndex))
JOIN DWH.DimDate d
  ON e.TradeDateId = d.DateId
 JOIN DWH.DimInstrument i
  ON i.instrumentid = e.instrumentid
WHERE d.DateId >= 20160201
AND i.instrumentid = 2

没有提示需要7秒,提示需要几分之一秒。 没有提示的查询计划是here。 带提示的查询计划为here

列存储索引的create语句是:

CREATE NONCLUSTERED COLUMNSTORE INDEX [FactEquityTradeNonClusteredColumnStoreIndex] ON [DWH].[FactEquityTrade]
(
    [EquityTradeID],
    [InstrumentID],
    [TradingSysTransNo],
    [TradeDateID],
    [TradeTimeID],
    [TradeTimestamp],
    [UTCTradeTimeStamp],
    [PublishDateID],
    [PublishTimeID],
    [PublishedDateTime],
    [UTCPublishedDateTime],
    [DelayedTradeYN],
    [EquityTradeJunkID],
    [BrokerID],
    [TraderID],
    [CurrencyID],
    [TradePrice],
    [BidPrice],
    [OfferPrice],
    [TradeVolume],
    [TradeTurnover],
    [TradeModificationTypeID],
    [InColumnStore],
    [TradeFileID],
    [BatchID],
    [CancelBatchID]
)
WHERE ([InColumnStore]=(1))
WITH (DROP_EXISTING = OFF, COMPRESSION_DELAY = 0) ON [PRIMARY]
GO

更新。 Plan using Count(EquityTradeID) instead of Count(*)hint included

3 个答案:

答案 0 :(得分:5)

您要求SQL Server选择一个简单的复杂查询计划。请注意,在使用提示时,SQL Server必须将columnstore索引与rowstore非聚集索引(UIWebView)连接起来。当仅使用行存储索引时,它可以进行搜索(我假设UIWebView是该索引的前导列)。它 仍然需要进行密钥查找,但它更简单。

我可以看到两个选项来在没有提示的情况下获得此行为:

首先,从列存储索引定义中删除IX_FactEquiteTradeInColumnStore并覆盖整个表。这就是您从专栏店询问的内容 - 涵盖所有内容。

如果无法做到这一点,您可以使用TradeDateId明确拆分数据:

InColumnStore

答案 1 :(得分:3)

您的索引是过滤索引(它有一个WHERE谓词)。

仅当查询的WHERE与索引的WHERE匹配时,优化程序才会使用此类索引。对于经典索引也是如此,对于列存储索引很可能也是如此。当优化器不使用过滤索引时,可能存在其他限制。

因此,要么将WHERE ([InColumnStore]=(1))添加到查询中,要么将其从索引定义中删除。

你在评论中说:“InColumnStore过滤器用于加载数据时的效率。到目前为止,所有测试过滤器都覆盖了所有行的100%”。这里的“所有行”是指“整个表的所有行”还是“结果集的所有行”?无论如何,很可能优化器不知道(即使它可能从统计数据中得到),这意味着使用这种索引的计划必须明确地执行额外的检查/查找,优化器认为这些检查/查找过于昂贵。

以下是关于此主题的几篇文章:

Why isn’t my filtered index being used? by Rob Farley

保罗怀特

Optimizer Limitations with Filtered Indexes

保罗怀特

An Unexpected Side-Effect of Adding a Filtered Index

Aaron Bertrand的

How filtered indexes could be a more powerful feature,请参阅优化限制部分。

答案 2 :(得分:-1)

试试这个: 桥接您的查询

Select * 
Into #DimDate
From DWH.DimDate
WHERE DateId >= 20160201

Select  COUNT(1), SUM(TradeTurnover), SUM(TradeVolume)
From DWH.FactEquityTrade e
Inner Join DWH.DimInstrument i ON i.instrumentid = e.instrumentid 
     And i.instrumentid = 2
Left Join #DimDate d ON e.TradeDateId = d.DateId

此查询的运行速度有多快?