我在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
答案 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
此查询的运行速度有多快?