为什么没有使用columnstore索引

Ror*_*ory 10 sql-server indexing query-performance columnstore sql-server-2016

我在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
Run Code Online (Sandbox Code Playgroud)

没有提示需要7秒,提示需要几分之一秒.没有提示的查询计划在这里.带有提示的查询计划在这里.

列存储索引的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
Run Code Online (Sandbox Code Playgroud)

更新.使用Count(EquityTradeID)而不是Count(*) 并使用提示计划

Ste*_*ble 5

您要求SQL Server选择一个简单的复杂查询计划.请注意,在使用提示时,SQL Server必须将列存储索引与rowstore非聚集索引(IX_FactEquiteTradeInColumnStore)连接在一起.当只使用行存储索引时,它可以进行搜索(我假设TradeDateId是该索引的前导列).这确实还要做一个键查找,但它更简单.

我可以看到两个选项来获得这种行为没有提示:

首先,InColumnStore从columnstore索引定义中删除并覆盖整个表.这就是你从专栏店要求的内容 - 涵盖一切.

如果这不可能,您可以使用a UNION ALL显式拆分数据:

WITH workaround
     AS (
         SELECT TradeDateId
              , instrumentid
              , TradeTurnover
              , TradeVolume
         FROM DWH.FactEquityTrade
         WHERE InColumnStore = 1
         UNION ALL
         SELECT TradeDateId
              , instrumentid
              , TradeTurnover
              , TradeVolume
         FROM DWH.FactEquityTrade
         WHERE InColumnStore = 0 -- Assuming this is a non-nullable BIT
        )
     SELECT COUNT(*)
          , SUM(TradeTurnover)
          , SUM(TradeVolume)
     FROM workaround e
          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;
Run Code Online (Sandbox Code Playgroud)