2016-12-08 304 views
1

我有一個包含定義調試信息表如下:與ROWNUMBER選擇需要長時間來執行

id INT NOT NULL IDENTITY 
message TEXT NOT NULL 
date DATETIME NOT NULL 

反對,我運行以下查詢:

SELECT * FROM (
    SELECT ROW_NUMBER() OVER (ORDER BY ID DESC) AS RowNum, * 
    FROM debug WHERE message LIKE @Filter 
) AS tbl 
WHERE RowNum > (@Page*200-200) 
AND RowNum <= (@Page * 200) 
ORDER BY ID DESC 

這給了我一個單頁200個結果;但在表中有220k個條目(並計數!),過濾和行編號需要相當長的時間(> 30秒)。

有什麼我可以做的,以加快獲得結果頁的過程?

編輯:所以我已經切換到VARCHAR(MAX)戈登建議;但這並沒有加快速度。查詢產生的執行計劃如下(我嘗試重新繪製圖形的ASCII藝術):

         Sequence Project      Clustered Index Scan 
    SELECT <- Sort <- Filter <- Top <- (Compute Scalar) <- Segment <- Filter <- [debug].[PK_debug] 
Cost: 0%  26%  0%  0%   0%    0%   2%   71% 

或XML:

<?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.2569.0" xmlns="http://schemas.microsoft.com/sqlserver/2004/07/showplan"> 
    <BatchSequence> 
    <Batch> 
     <Statements> 
     <StmtSimple StatementCompId="4" StatementEstRows="16.4317" StatementId="1" StatementOptmLevel="FULL" StatementOptmEarlyAbortReason="GoodEnoughPlanFound" CardinalityEstimationModelVersion="120" StatementSubTreeCost="0.0438369" StatementText="SELECT * FROM (SELECT ROW_NUMBER() OVER (ORDER BY ID DESC) AS RowNum, * FROM debug WHERE message LIKE @Filter) AS tbl WHERE RowNum &gt; (@Page*200-200) AND RowNum &lt;= (@Page * 200) ORDER BY ID DESC" StatementType="SELECT" QueryHash="0x535D30B424597DBB" QueryPlanHash="0x17ABB516DFF1A1A7" 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 DegreeOfParallelism="0" NonParallelPlanReason="EstimatedDOPIsOne" MemoryGrant="1024" CachedPlanSize="32" CompileTime="4" CompileCPU="4" CompileMemory="248"> 
      <MemoryGrantInfo SerialRequiredMemory="512" SerialDesiredMemory="672" RequiredMemory="512" DesiredMemory="672" RequestedMemory="1024" GrantWaitTime="0" GrantedMemory="1024" MaxUsedMemory="56" /> 
      <OptimizerHardwareDependentProperties EstimatedAvailableMemoryGrant="256000" EstimatedPagesCached="16000" EstimatedAvailableDegreeOfParallelism="1" /> 
      <RelOp AvgRowSize="4055" EstimateCPU="0.000207573" EstimateIO="0.0112613" EstimateRebinds="0" EstimateRewinds="0" EstimatedExecutionMode="Row" EstimateRows="16.4317" LogicalOp="Sort" NodeId="0" Parallel="false" PhysicalOp="Sort" EstimatedTotalSubtreeCost="0.0438369"> 
       <OutputList> 
       <ColumnReference Database="[timeflex]" Schema="[dbo]" Table="[debug]" Column="id" /> 
       <ColumnReference Database="[timeflex]" Schema="[dbo]" Table="[debug]" Column="message" /> 
       <ColumnReference Database="[timeflex]" Schema="[dbo]" Table="[debug]" Column="date" /> 
       <ColumnReference Column="Expr1002" /> 
       </OutputList> 
       <MemoryFractions Input="1" Output="1" /> 
       <RunTimeInformation> 
       <RunTimeCountersPerThread Thread="0" ActualRebinds="1" ActualRewinds="0" ActualRows="147" ActualEndOfScans="1" ActualExecutions="1" /> 
       </RunTimeInformation> 
       <Sort Distinct="false"> 
       <OrderBy> 
        <OrderByColumn Ascending="false"> 
        <ColumnReference Database="[timeflex]" Schema="[dbo]" Table="[debug]" Column="id" /> 
        </OrderByColumn> 
       </OrderBy> 
       <RelOp AvgRowSize="4055" EstimateCPU="8.8E-05" EstimateIO="0" EstimateRebinds="0" EstimateRewinds="0" EstimatedExecutionMode="Row" EstimateRows="16.4317" LogicalOp="Filter" NodeId="1" Parallel="false" PhysicalOp="Filter" EstimatedTotalSubtreeCost="0.0323681"> 
        <OutputList> 
        <ColumnReference Database="[timeflex]" Schema="[dbo]" Table="[debug]" Column="id" /> 
        <ColumnReference Database="[timeflex]" Schema="[dbo]" Table="[debug]" Column="message" /> 
        <ColumnReference Database="[timeflex]" Schema="[dbo]" Table="[debug]" Column="date" /> 
        <ColumnReference Column="Expr1002" /> 
        </OutputList> 
        <RunTimeInformation> 
        <RunTimeCountersPerThread Thread="0" ActualRows="147" ActualEndOfScans="1" ActualExecutions="1" /> 
        </RunTimeInformation> 
        <Filter StartupExpression="false"> 
        <RelOp AvgRowSize="4055" EstimateCPU="1E-05" EstimateIO="0" EstimateRebinds="0" EstimateRewinds="0" EstimatedExecutionMode="Row" EstimateRows="100" LogicalOp="Top" NodeId="2" Parallel="false" PhysicalOp="Top" EstimatedTotalSubtreeCost="0.0322801"> 
         <OutputList> 
         <ColumnReference Database="[timeflex]" Schema="[dbo]" Table="[debug]" Column="id" /> 
         <ColumnReference Database="[timeflex]" Schema="[dbo]" Table="[debug]" Column="message" /> 
         <ColumnReference Database="[timeflex]" Schema="[dbo]" Table="[debug]" Column="date" /> 
         <ColumnReference Column="Expr1002" /> 
         </OutputList> 
         <RunTimeInformation> 
         <RunTimeCountersPerThread Thread="0" ActualRows="147" ActualEndOfScans="1" ActualExecutions="1" /> 
         </RunTimeInformation> 
         <Top RowCount="false" IsPercent="false" WithTies="false"> 
         <TopExpression> 
          <ScalarOperator ScalarString="CASE WHEN CONVERT_IMPLICIT(bigint,[@Page]*(200),0) IS NULL OR CONVERT_IMPLICIT(bigint,[@Page]*(200),0)&lt;(0) THEN (0) ELSE CONVERT_IMPLICIT(bigint,[@Page]*(200),0) END"> 
          <IF> 
           <Condition> 
           <ScalarOperator> 
            <Logical Operation="OR"> 
            <ScalarOperator> 
             <Compare CompareOp="IS"> 
             <ScalarOperator> 
              <Identifier> 
              <ColumnReference Column="ConstExpr1007"> 
               <ScalarOperator> 
               <Convert DataType="bigint" Style="0" Implicit="true"> 
                <ScalarOperator> 
                <Arithmetic Operation="MULT"> 
                 <ScalarOperator> 
                 <Identifier> 
                  <ColumnReference Column="@Page" /> 
                 </Identifier> 
                 </ScalarOperator> 
                 <ScalarOperator> 
                 <Const ConstValue="(200)" /> 
                 </ScalarOperator> 
                </Arithmetic> 
                </ScalarOperator> 
               </Convert> 
               </ScalarOperator> 
              </ColumnReference> 
              </Identifier> 
             </ScalarOperator> 
             <ScalarOperator> 
              <Const ConstValue="NULL" /> 
             </ScalarOperator> 
             </Compare> 
            </ScalarOperator> 
            <ScalarOperator> 
             <Compare CompareOp="LT"> 
             <ScalarOperator> 
              <Identifier> 
              <ColumnReference Column="ConstExpr1007"> 
               <ScalarOperator> 
               <Convert DataType="bigint" Style="0" Implicit="true"> 
                <ScalarOperator> 
                <Arithmetic Operation="MULT"> 
                 <ScalarOperator> 
                 <Identifier> 
                  <ColumnReference Column="@Page" /> 
                 </Identifier> 
                 </ScalarOperator> 
                 <ScalarOperator> 
                 <Const ConstValue="(200)" /> 
                 </ScalarOperator> 
                </Arithmetic> 
                </ScalarOperator> 
               </Convert> 
               </ScalarOperator> 
              </ColumnReference> 
              </Identifier> 
             </ScalarOperator> 
             <ScalarOperator> 
              <Const ConstValue="(0)" /> 
             </ScalarOperator> 
             </Compare> 
            </ScalarOperator> 
            </Logical> 
           </ScalarOperator> 
           </Condition> 
           <Then> 
           <ScalarOperator> 
            <Const ConstValue="(0)" /> 
           </ScalarOperator> 
           </Then> 
           <Else> 
           <ScalarOperator> 
            <Identifier> 
            <ColumnReference Column="ConstExpr1007"> 
             <ScalarOperator> 
             <Convert DataType="bigint" Style="0" Implicit="true"> 
              <ScalarOperator> 
              <Arithmetic Operation="MULT"> 
               <ScalarOperator> 
               <Identifier> 
                <ColumnReference Column="@Page" /> 
               </Identifier> 
               </ScalarOperator> 
               <ScalarOperator> 
               <Const ConstValue="(200)" /> 
               </ScalarOperator> 
              </Arithmetic> 
              </ScalarOperator> 
             </Convert> 
             </ScalarOperator> 
            </ColumnReference> 
            </Identifier> 
           </ScalarOperator> 
           </Else> 
          </IF> 
          </ScalarOperator> 
         </TopExpression> 
         <RelOp AvgRowSize="4055" EstimateCPU="0.00284444" EstimateIO="0" EstimateRebinds="0" EstimateRewinds="0" EstimatedExecutionMode="Row" EstimateRows="100" LogicalOp="Compute Scalar" NodeId="3" Parallel="false" PhysicalOp="Sequence Project" EstimatedTotalSubtreeCost="0.0322701"> 
          <OutputList> 
          <ColumnReference Database="[timeflex]" Schema="[dbo]" Table="[debug]" Column="id" /> 
          <ColumnReference Database="[timeflex]" Schema="[dbo]" Table="[debug]" Column="message" /> 
          <ColumnReference Database="[timeflex]" Schema="[dbo]" Table="[debug]" Column="date" /> 
          <ColumnReference Column="Expr1002" /> 
          </OutputList> 
          <RunTimeInformation> 
          <RunTimeCountersPerThread Thread="0" ActualRows="147" ActualEndOfScans="1" ActualExecutions="1" /> 
          </RunTimeInformation> 
          <SequenceProject> 
          <DefinedValues> 
           <DefinedValue> 
           <ColumnReference Column="Expr1002" /> 
           <ScalarOperator ScalarString="row_number"> 
            <Sequence FunctionName="row_number" /> 
           </ScalarOperator> 
           </DefinedValue> 
          </DefinedValues> 
          <RelOp AvgRowSize="4055" EstimateCPU="0.00071111" EstimateIO="0" EstimateRebinds="0" EstimateRewinds="0" EstimatedExecutionMode="Row" EstimateRows="100" LogicalOp="Segment" NodeId="4" Parallel="false" PhysicalOp="Segment" EstimatedTotalSubtreeCost="0.0322621"> 
           <OutputList> 
           <ColumnReference Database="[timeflex]" Schema="[dbo]" Table="[debug]" Column="id" /> 
           <ColumnReference Database="[timeflex]" Schema="[dbo]" Table="[debug]" Column="message" /> 
           <ColumnReference Database="[timeflex]" Schema="[dbo]" Table="[debug]" Column="date" /> 
           <ColumnReference Column="Segment1008" /> 
           </OutputList> 
           <RunTimeInformation> 
           <RunTimeCountersPerThread Thread="0" ActualRows="147" ActualEndOfScans="1" ActualExecutions="1" /> 
           </RunTimeInformation> 
           <Segment> 
           <GroupBy /> 
           <SegmentColumn> 
            <ColumnReference Column="Segment1008" /> 
           </SegmentColumn> 
           <RelOp AvgRowSize="4047" EstimateCPU="0.347654" EstimateIO="0" EstimateRebinds="0" EstimateRewinds="0" EstimatedExecutionMode="Row" EstimateRows="100" LogicalOp="Filter" NodeId="5" Parallel="false" PhysicalOp="Filter" EstimatedTotalSubtreeCost="0.0322601"> 
            <OutputList> 
            <ColumnReference Database="[timeflex]" Schema="[dbo]" Table="[debug]" Column="id" /> 
            <ColumnReference Database="[timeflex]" Schema="[dbo]" Table="[debug]" Column="message" /> 
            <ColumnReference Database="[timeflex]" Schema="[dbo]" Table="[debug]" Column="date" /> 
            </OutputList> 
            <RunTimeInformation> 
            <RunTimeCountersPerThread Thread="0" ActualRows="147" ActualEndOfScans="1" ActualExecutions="1" /> 
            </RunTimeInformation> 
            <Filter StartupExpression="false"> 
            <RelOp AvgRowSize="4047" EstimateCPU="0.434724" EstimateIO="9.53275" EstimateRebinds="0" EstimateRewinds="0" EstimatedExecutionMode="Row" EstimateRows="1111.11" LogicalOp="Clustered Index Scan" NodeId="6" Parallel="false" PhysicalOp="Clustered Index Scan" EstimatedTotalSubtreeCost="0.0312823" TableCardinality="395061"> 
             <OutputList> 
             <ColumnReference Database="[timeflex]" Schema="[dbo]" Table="[debug]" Column="id" /> 
             <ColumnReference Database="[timeflex]" Schema="[dbo]" Table="[debug]" Column="message" /> 
             <ColumnReference Database="[timeflex]" Schema="[dbo]" Table="[debug]" Column="date" /> 
             </OutputList> 
             <RunTimeInformation> 
             <RunTimeCountersPerThread Thread="0" ActualRows="395061" ActualEndOfScans="1" ActualExecutions="1" /> 
             </RunTimeInformation> 
             <IndexScan Ordered="true" ScanDirection="BACKWARD" ForcedIndex="false" ForceSeek="false" ForceScan="false" NoExpandHint="false" Storage="RowStore"> 
             <DefinedValues> 
              <DefinedValue> 
              <ColumnReference Database="[timeflex]" Schema="[dbo]" Table="[debug]" Column="id" /> 
              </DefinedValue> 
              <DefinedValue> 
              <ColumnReference Database="[timeflex]" Schema="[dbo]" Table="[debug]" Column="message" /> 
              </DefinedValue> 
              <DefinedValue> 
              <ColumnReference Database="[timeflex]" Schema="[dbo]" Table="[debug]" Column="date" /> 
              </DefinedValue> 
             </DefinedValues> 
             <Object Database="[timeflex]" Schema="[dbo]" Table="[debug]" Index="[PK_debug]" IndexKind="Clustered" Storage="RowStore" /> 
             </IndexScan> 
            </RelOp> 
            <Predicate> 
             <ScalarOperator ScalarString="[timeflex].[dbo].[debug].[message] like [@Filter]"> 
             <Intrinsic FunctionName="like"> 
              <ScalarOperator> 
              <Identifier> 
               <ColumnReference Database="[timeflex]" Schema="[dbo]" Table="[debug]" Column="message" /> 
              </Identifier> 
              </ScalarOperator> 
              <ScalarOperator> 
              <Identifier> 
               <ColumnReference Column="@Filter" /> 
              </Identifier> 
              </ScalarOperator> 
             </Intrinsic> 
             </ScalarOperator> 
            </Predicate> 
            </Filter> 
           </RelOp> 
           </Segment> 
          </RelOp> 
          </SequenceProject> 
         </RelOp> 
         </Top> 
        </RelOp> 
        <Predicate> 
         <ScalarOperator ScalarString="[Expr1002]&gt;CONVERT_IMPLICIT(bigint,[@Page]*(200)-(200),0) AND [Expr1002]&lt;=CONVERT_IMPLICIT(bigint,[@Page]*(200),0)"> 
         <Logical Operation="AND"> 
          <ScalarOperator> 
          <Compare CompareOp="GT"> 
           <ScalarOperator> 
           <Identifier> 
            <ColumnReference Column="Expr1002" /> 
           </Identifier> 
           </ScalarOperator> 
           <ScalarOperator> 
           <Identifier> 
            <ColumnReference Column="ConstExpr1006"> 
            <ScalarOperator> 
             <Convert DataType="bigint" Style="0" Implicit="true"> 
             <ScalarOperator> 
              <Arithmetic Operation="SUB"> 
              <ScalarOperator> 
               <Arithmetic Operation="MULT"> 
               <ScalarOperator> 
                <Identifier> 
                <ColumnReference Column="@Page" /> 
                </Identifier> 
               </ScalarOperator> 
               <ScalarOperator> 
                <Const ConstValue="(200)" /> 
               </ScalarOperator> 
               </Arithmetic> 
              </ScalarOperator> 
              <ScalarOperator> 
               <Const ConstValue="(200)" /> 
              </ScalarOperator> 
              </Arithmetic> 
             </ScalarOperator> 
             </Convert> 
            </ScalarOperator> 
            </ColumnReference> 
           </Identifier> 
           </ScalarOperator> 
          </Compare> 
          </ScalarOperator> 
          <ScalarOperator> 
          <Compare CompareOp="LE"> 
           <ScalarOperator> 
           <Identifier> 
            <ColumnReference Column="Expr1002" /> 
           </Identifier> 
           </ScalarOperator> 
           <ScalarOperator> 
           <Identifier> 
            <ColumnReference Column="ConstExpr1007"> 
            <ScalarOperator> 
             <Convert DataType="bigint" Style="0" Implicit="true"> 
             <ScalarOperator> 
              <Arithmetic Operation="MULT"> 
              <ScalarOperator> 
               <Identifier> 
               <ColumnReference Column="@Page" /> 
               </Identifier> 
              </ScalarOperator> 
              <ScalarOperator> 
               <Const ConstValue="(200)" /> 
              </ScalarOperator> 
              </Arithmetic> 
             </ScalarOperator> 
             </Convert> 
            </ScalarOperator> 
            </ColumnReference> 
           </Identifier> 
           </ScalarOperator> 
          </Compare> 
          </ScalarOperator> 
         </Logical> 
         </ScalarOperator> 
        </Predicate> 
        </Filter> 
       </RelOp> 
       </Sort> 
      </RelOp> 
      <ParameterList> 
       <ColumnReference Column="@Page" ParameterRuntimeValue="(1)" /> 
       <ColumnReference Column="@Filter" ParameterRuntimeValue="'%ZUser888%'" /> 
      </ParameterList> 
      </QueryPlan> 
     </StmtSimple> 
     </Statements> 
    </Batch> 
    </BatchSequence> 
</ShowPlanXML> 
+5

你怎麼知道問題是'row_number()'而不是'like'?此外,在更新版本的SQL Server中,您可以使用'OFFSET' /'FETCH'進行分頁。 –

+0

這將掃描所有220K條目。 ROW_NUMBER不是瓶頸,然而,在我看來,30多秒是用於查詢的時間。 –

+0

@GordonLinoff在我的情況下,它是Microsoft SQL Server 2014(RTM-CU14)(KB3158271) - 12.0.2569.0(X64)2016年5月27日15:06:08 Copyright(c)Microsoft Corporation Standard Edition(64-bit)on Windows NT 6.3 (Build 9600:)(Hypervisor)',但它至少要在2010年,2012年,2014年和2016年工作。另外,我寫了「過濾和行編號」,其中「過濾」就是LIKE。 – Alexander

回答

5

這是太長了評論。

首先,請勿使用text,請使用varchar(max)nvarchar(max)。它在SQL Server 2016中被正式棄用,所以它可能會在未來的版本中消失。

對於分頁,請使用OFFSET/FETCH。這是在SQL Server 2012中引入的,因此它稍微兼容。沒有SQL Server 2010.閱讀它here

讓我排除表/頁/行爭用作爲性能問題的原因。我最好的猜測是like在很寬的一列。如果message確實是一堆自由形式的文本,則使用全文索引。文檔是開始的地方。出於某種原因,我現在與微軟文檔的鏈接不能很好地工作,但應該很容易找到。

如果行寬真的很寬,那麼select *可能還有一個額外的問題。如果您正在進行分頁,那麼這可能是用戶界面,所以您可能希望將列限制爲您真正需要的列 - 如果不打算顯示整列,甚至可以縮短很長的列。

+0

好的,我2010年錯了,我們仍然支持2008年。 – Alexander

相關問題