加速慢速SELECT DISTINCT查询SQL Server的解决方案

时间:2015-02-10 10:02:33

标签: sql sql-server performance

这与(Solution for speeding up a slow SELECT DISTINCT query in Postgres

中提出的问题基本相同

这是相同的情况,一个庞大的部署数据库,由于旧的遗留应用程序,无法对其进行规范化。不断添加新行,并删除旧行以满足某些标准。 我通过使用CTE尝试了这个建议,我发现这里没有性能提升, 与原始

的执行时间相同
select distinct [somecolumn] 
from bigtable

同样适用于使用Group by的建议。

看起来效果最好的是建议创建视图并查询视图。 (缓存已在查询之间重置)

我在此需要一些建议,因为我不明白为什么这会带来更好的表现。

create view [dbo].[vwDistinct]
with schemabinding
as 
   select 
      [somecolumn], count_big(*) as TableCount
   from 
      dbo.BigTable 
   where
      somecolumn IS NOT NULL
   group by 
      somecolumn;

select distinct somecolumn 
from vwDistinct

应用程序使用存储过程进行调用。该数据库位于SQL Server 2008 R2上,但如果有充分的理由,可以将其移至SQL Server 2014。

谢谢

这是执行计划     从vwDistinct

中选择一些列
<?xml version="1.0" encoding="utf-16"?>
<ShowPlanXML xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" Version="1.2" Build="12.0.2000.8" xmlns="http://schemas.microsoft.com/sqlserver/2004/07/showplan">
  <BatchSequence>
    <Batch>
      <Statements>
        <StmtSimple StatementCompId="1" StatementEstRows="41138.3" StatementId="1" StatementOptmLevel="FULL" CardinalityEstimationModelVersion="70" StatementSubTreeCost="5.10782" StatementText="select somecolumn from vwDistinct" StatementType="SELECT" QueryHash="0x23700E4CF62A8E4E" QueryPlanHash="0x79D8240601D270CB" RetrievedFromCache="true">
          <StatementSetOptions ANSI_NULLS="true" ANSI_PADDING="true" ANSI_WARNINGS="true" ARITHABORT="true" CONCAT_NULL_YIELDS_NULL="true" NUMERIC_ROUNDABORT="false" QUOTED_IDENTIFIER="true" />
          <QueryPlan NonParallelPlanReason="EstimatedDOPIsOne" CachedPlanSize="16" CompileTime="59" CompileCPU="18" CompileMemory="336">
            <MemoryGrantInfo SerialRequiredMemory="0" SerialDesiredMemory="0" />
            <OptimizerHardwareDependentProperties EstimatedAvailableMemoryGrant="1239807" EstimatedPagesCached="77487" EstimatedAvailableDegreeOfParallelism="1" />
            <RelOp AvgRowSize="37" EstimateCPU="1.03877" EstimateIO="4.06905" EstimateRebinds="0" EstimateRewinds="0" EstimatedExecutionMode="Row" EstimateRows="944197" LogicalOp="Clustered Index Scan" NodeId="1" Parallel="false" PhysicalOp="Clustered Index Scan" EstimatedTotalSubtreeCost="5.10782" TableCardinality="944197">
              <OutputList>
                <ColumnReference Database="[BigData]" Schema="[dbo]" Table="[vwDistinct]" Column="somecolumn" />
              </OutputList>
              <IndexScan Ordered="false" ForcedIndex="false" ForceScan="false" NoExpandHint="true" Storage="RowStore">
                <DefinedValues>
                  <DefinedValue>
                    <ColumnReference Database="[BigData]" Schema="[dbo]" Table="[vwDistinct]" Column="somecolumn" />
                  </DefinedValue>
                </DefinedValues>
                <Object Database="[BigData]" Schema="[dbo]" Table="[vwDistinct]" Index="[cdxDistinct]" IndexKind="ViewClustered" Storage="RowStore" />
                <IndexedViewInfo>
                  <Object Database="[BigData]" Schema="[dbo]" Table="[BigTable]" />
                </IndexedViewInfo>
              </IndexScan>
            </RelOp>
          </QueryPlan>
        </StmtSimple>
      </Statements>
    </Batch>
  </BatchSequence>
</ShowPlanXML>

1 个答案:

答案 0 :(得分:3)

<Object Database="[BigData]" Schema="[dbo]" Table="[vwDistinct]" Index="[cdxDistinct]" IndexKind="ViewClustered" Storage="RowStore" /> 

表示您的视图已编入索引。根据你所说的评论

  

大约2.5-3-3万行,大约有100个不同的值。

查询

select distinct [somecolumn] 
from bigtable
没有视图的

将扫描表索引中的250多万行,以找到所有不同的值。

但是,视图只包含100行。因此,当它存在时,它可以对视图的聚集索引执行扫描,以查找所有不同的值。

成本是所有插入和修改somecolumn的任何更新都会更加昂贵。