今天我在我们的代码中发现了这个查询,它从我们的数据库中提取错误列表:
SELECT *
FROM (
SELECT Substring(title, 9, Patindex('%)%', title) - 9) AS SERVICE, *
FROM core.LOG
WHERE logtypeid = 1
AND title LIKE 'Error: (%'
AND lastmodified > '2010-06-21T00:00:00'
AND lastmodified < '2010-06-22T00:00:00'
) serviceerrors
WHERE SERVICE = 'CheckHelpDeskEmail'
失败并出现以下错误:
传递给的无效长度参数 SUBSTRING功能。
如果我删除最后一行的WHERE
子句,它可以正常工作。或者,如果我从内部子查询中取出WHERE
子句并将其移动到主查询,它可以正常工作。所以这有效:
SELECT *
FROM (
SELECT Substring(title, 9, Patindex('%)%', title) - 9) AS SERVICE, *
FROM core.LOG
) serviceerrors
WHERE logtypeid = 1
AND title LIKE 'Error: (%'
AND lastmodified > '2010-06-21T00:00:00'
AND lastmodified < '2010-06-22T00:00:00'
AND SERVICE = 'CheckHelpDeskEmail'
有谁知道为什么?我认为问题是SQL实际上是通过core.LOG表进行多次运行,并且它第一次只是在整个表上运行子串行而失败,因为某些行不会有')'。但是,如果它运行WHERE
子句中的其余行,则不会找到任何缺少')'的行。然后它再次运行core.LOG表并运行其余的过滤器。这似乎是无效的,因为它将最终在数百万行上运行Substring函数,而在WHERE
子句中的剩余过滤器中运行大约15行。
这是我的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.0" Build="9.00.3310.00" xmlns="http://schemas.microsoft.com/sqlserver/2004/07/showplan">
<BatchSequence>
<Batch>
<Statements>
<StmtSimple StatementCompId="1" StatementEstRows="1" StatementId="1" StatementOptmLevel="FULL" StatementSubTreeCost="36.4574" StatementText="SELECT *
FROM (
 SELECT Substring(title, 9, Patindex('%)%', title) - 9) AS SERVICE,
 *
 FROM core.LOG
 WHERE logtypeid = 1
 AND title LIKE 'Error: (%'
 AND lastmodified > '2010-06-21T00:00:00'
 AND lastmodified < '2010-06-22T00:00:00'
 ) serviceerrors
WHERE SERVICE = 'CheckHelpDeskEmail' 
" StatementType="SELECT">
<StatementSetOptions ANSI_NULLS="false" ANSI_PADDING="false" ANSI_WARNINGS="false" ARITHABORT="true" CONCAT_NULL_YIELDS_NULL="false" NUMERIC_ROUNDABORT="false" QUOTED_IDENTIFIER="false" />
<QueryPlan CachedPlanSize="47" CompileTime="10" CompileCPU="7" CompileMemory="544">
<RelOp AvgRowSize="4544" EstimateCPU="1E-07" EstimateIO="0" EstimateRebinds="0" EstimateRewinds="0" EstimateRows="1" LogicalOp="Compute Scalar" NodeId="0" Parallel="false" PhysicalOp="Compute Scalar" EstimatedTotalSubtreeCost="36.4574">
<OutputList>
<ColumnReference Database="[Aqueduct]" Schema="[Core]" Table="[Log]" Column="LogId" />
<ColumnReference Database="[Aqueduct]" Schema="[Core]" Table="[Log]" Column="Title" />
<ColumnReference Database="[Aqueduct]" Schema="[Core]" Table="[Log]" Column="Details" />
<ColumnReference Database="[Aqueduct]" Schema="[Core]" Table="[Log]" Column="IdentifierHash" />
<ColumnReference Database="[Aqueduct]" Schema="[Core]" Table="[Log]" Column="LastModifier" />
<ColumnReference Database="[Aqueduct]" Schema="[Core]" Table="[Log]" Column="LastModified" />
<ColumnReference Database="[Aqueduct]" Schema="[Core]" Table="[Log]" Column="LogTypeId" />
<ColumnReference Column="Expr1003" />
</OutputList>
<ComputeScalar>
<DefinedValues>
<DefinedValue>
<ColumnReference Column="Expr1003" />
<ScalarOperator ScalarString="substring([Aqueduct].[Core].[Log].[Title],(9),patindex(N'%)%',[Aqueduct].[Core].[Log].[Title])-(9))">
<Intrinsic FunctionName="substring">
<ScalarOperator>
<Identifier>
<ColumnReference Database="[Aqueduct]" Schema="[Core]" Table="[Log]" Column="Title" />
</Identifier>
</ScalarOperator>
<ScalarOperator>
<Const ConstValue="(9)" />
</ScalarOperator>
<ScalarOperator>
<Arithmetic Operation="SUB">
<ScalarOperator>
<Intrinsic FunctionName="patindex">
<ScalarOperator>
<Const ConstValue="N'%)%'" />
</ScalarOperator>
<ScalarOperator>
<Identifier>
<ColumnReference Database="[Aqueduct]" Schema="[Core]" Table="[Log]" Column="Title" />
</Identifier>
</ScalarOperator>
</Intrinsic>
</ScalarOperator>
<ScalarOperator>
<Const ConstValue="(9)" />
</ScalarOperator>
</Arithmetic>
</ScalarOperator>
</Intrinsic>
</ScalarOperator>
</DefinedValue>
</DefinedValues>
<RelOp AvgRowSize="4342" EstimateCPU="0.0288036" EstimateIO="0" EstimateRebinds="0" EstimateRewinds="0" EstimateRows="1" LogicalOp="Gather Streams" NodeId="1" Parallel="true" PhysicalOp="Parallelism" EstimatedTotalSubtreeCost="36.4574">
<OutputList>
<ColumnReference Database="[Aqueduct]" Schema="[Core]" Table="[Log]" Column="LogId" />
<ColumnReference Database="[Aqueduct]" Schema="[Core]" Table="[Log]" Column="Title" />
<ColumnReference Database="[Aqueduct]" Schema="[Core]" Table="[Log]" Column="Details" />
<ColumnReference Database="[Aqueduct]" Schema="[Core]" Table="[Log]" Column="IdentifierHash" />
<ColumnReference Database="[Aqueduct]" Schema="[Core]" Table="[Log]" Column="LastModifier" />
<ColumnReference Database="[Aqueduct]" Schema="[Core]" Table="[Log]" Column="LastModified" />
<ColumnReference Database="[Aqueduct]" Schema="[Core]" Table="[Log]" Column="LogTypeId" />
</OutputList>
<Parallelism>
<RelOp AvgRowSize="4342" EstimateCPU="0.0128582" EstimateIO="0" EstimateRebinds="0" EstimateRewinds="0" EstimateRows="1" LogicalOp="Filter" NodeId="2" Parallel="true" PhysicalOp="Filter" EstimatedTotalSubtreeCost="36.4286">
<OutputList>
<ColumnReference Database="[Aqueduct]" Schema="[Core]" Table="[Log]" Column="LogId" />
<ColumnReference Database="[Aqueduct]" Schema="[Core]" Table="[Log]" Column="Title" />
<ColumnReference Database="[Aqueduct]" Schema="[Core]" Table="[Log]" Column="Details" />
<ColumnReference Database="[Aqueduct]" Schema="[Core]" Table="[Log]" Column="IdentifierHash" />
<ColumnReference Database="[Aqueduct]" Schema="[Core]" Table="[Log]" Column="LastModifier" />
<ColumnReference Database="[Aqueduct]" Schema="[Core]" Table="[Log]" Column="LastModified" />
<ColumnReference Database="[Aqueduct]" Schema="[Core]" Table="[Log]" Column="LogTypeId" />
</OutputList>
<Filter StartupExpression="false">
<RelOp AvgRowSize="4342" EstimateCPU="0.0235734" EstimateIO="0" EstimateRebinds="0" EstimateRewinds="0" EstimateRows="11279.1" LogicalOp="Inner Join" NodeId="3" Parallel="true" PhysicalOp="Nested Loops" EstimatedTotalSubtreeCost="36.4157">
<OutputList>
<ColumnReference Database="[Aqueduct]" Schema="[Core]" Table="[Log]" Column="LogId" />
<ColumnReference Database="[Aqueduct]" Schema="[Core]" Table="[Log]" Column="Title" />
<ColumnReference Database="[Aqueduct]" Schema="[Core]" Table="[Log]" Column="Details" />
<ColumnReference Database="[Aqueduct]" Schema="[Core]" Table="[Log]" Column="IdentifierHash" />
<ColumnReference Database="[Aqueduct]" Schema="[Core]" Table="[Log]" Column="LastModifier" />
<ColumnReference Database="[Aqueduct]" Schema="[Core]" Table="[Log]" Column="LastModified" />
<ColumnReference Database="[Aqueduct]" Schema="[Core]" Table="[Log]" Column="LogTypeId" />
</OutputList>
<NestedLoops Optimized="true" WithUnorderedPrefetch="true">
<OuterReferences>
<ColumnReference Database="[Aqueduct]" Schema="[Core]" Table="[Log]" Column="LogId" />
<ColumnReference Column="Expr1004" />
</OuterReferences>
<RelOp AvgRowSize="19" EstimateCPU="0.00628203" EstimateIO="0.0186806" EstimateRebinds="0" EstimateRewinds="0" EstimateRows="11279.1" LogicalOp="Index Seek" NodeId="6" Parallel="true" PhysicalOp="Index Seek" EstimatedTotalSubtreeCost="0.0249626">
<OutputList>
<ColumnReference Database="[Aqueduct]" Schema="[Core]" Table="[Log]" Column="LogId" />
<ColumnReference Database="[Aqueduct]" Schema="[Core]" Table="[Log]" Column="LastModified" />
</OutputList>
<IndexScan Ordered="true" ScanDirection="FORWARD" ForcedIndex="false" NoExpandHint="false">
<DefinedValues>
<DefinedValue>
<ColumnReference Database="[Aqueduct]" Schema="[Core]" Table="[Log]" Column="LogId" />
</DefinedValue>
<DefinedValue>
<ColumnReference Database="[Aqueduct]" Schema="[Core]" Table="[Log]" Column="LastModified" />
</DefinedValue>
</DefinedValues>
<Object Database="[Aqueduct]" Schema="[Core]" Table="[Log]" Index="[IX_LastModified]" />
<SeekPredicates>
<SeekPredicate>
<StartRange ScanType="GT">
<RangeColumns>
<ColumnReference Database="[Aqueduct]" Schema="[Core]" Table="[Log]" Column="LastModified" />
</RangeColumns>
<RangeExpressions>
<ScalarOperator ScalarString="'2010-06-21 00:00:00.000'">
<Const ConstValue="'2010-06-21 00:00:00.000'" />
</ScalarOperator>
</RangeExpressions>
</StartRange>
<EndRange ScanType="LT">
<RangeColumns>
<ColumnReference Database="[Aqueduct]" Schema="[Core]" Table="[Log]" Column="LastModified" />
</RangeColumns>
<RangeExpressions>
<ScalarOperator ScalarString="'2010-06-22 00:00:00.000'">
<Const ConstValue="'2010-06-22 00:00:00.000'" />
</ScalarOperator>
</RangeExpressions>
</EndRange>
</SeekPredicate>
</SeekPredicates>
</IndexScan>
</RelOp>
<RelOp AvgRowSize="4447" EstimateCPU="0.0001581" EstimateIO="0.003125" EstimateRebinds="11278.1" EstimateRewinds="0" EstimateRows="1" LogicalOp="Clustered Index Seek" NodeId="8" Parallel="true" PhysicalOp="Clustered Index Seek" EstimatedTotalSubtreeCost="36.3672">
<OutputList>
<ColumnReference Database="[Aqueduct]" Schema="[Core]" Table="[Log]" Column="Title" />
<ColumnReference Database="[Aqueduct]" Schema="[Core]" Table="[Log]" Column="Details" />
<ColumnReference Database="[Aqueduct]" Schema="[Core]" Table="[Log]" Column="IdentifierHash" />
<ColumnReference Database="[Aqueduct]" Schema="[Core]" Table="[Log]" Column="LastModifier" />
<ColumnReference Database="[Aqueduct]" Schema="[Core]" Table="[Log]" Column="LogTypeId" />
</OutputList>
<IndexScan Lookup="true" Ordered="true" ScanDirection="FORWARD" ForcedIndex="false" NoExpandHint="false">
<DefinedValues>
<DefinedValue>
<ColumnReference Database="[Aqueduct]" Schema="[Core]" Table="[Log]" Column="Title" />
</DefinedValue>
<DefinedValue>
<ColumnReference Database="[Aqueduct]" Schema="[Core]" Table="[Log]" Column="Details" />
</DefinedValue>
<DefinedValue>
<ColumnReference Database="[Aqueduct]" Schema="[Core]" Table="[Log]" Column="IdentifierHash" />
</DefinedValue>
<DefinedValue>
<ColumnReference Database="[Aqueduct]" Schema="[Core]" Table="[Log]" Column="LastModifier" />
</DefinedValue>
<DefinedValue>
<ColumnReference Database="[Aqueduct]" Schema="[Core]" Table="[Log]" Column="LogTypeId" />
</DefinedValue>
</DefinedValues>
<Object Database="[Aqueduct]" Schema="[Core]" Table="[Log]" Index="[PK_Core_Log]" TableReferenceId="-1" />
<SeekPredicates>
<SeekPredicate>
<Prefix ScanType="EQ">
<RangeColumns>
<ColumnReference Database="[Aqueduct]" Schema="[Core]" Table="[Log]" Column="LogId" />
</RangeColumns>
<RangeExpressions>
<ScalarOperator ScalarString="[Aqueduct].[Core].[Log].[LogId]">
<Identifier>
<ColumnReference Database="[Aqueduct]" Schema="[Core]" Table="[Log]" Column="LogId" />
</Identifier>
</ScalarOperator>
</RangeExpressions>
</Prefix>
</SeekPredicate>
</SeekPredicates>
</IndexScan>
</RelOp>
</NestedLoops>
</RelOp>
<Predicate>
<ScalarOperator ScalarString="substring([Aqueduct].[Core].[Log].[Title],(9),patindex(N'%)%',[Aqueduct].[Core].[Log].[Title])-(9))=N'CheckHelpDeskEmail' AND [Aqueduct].[Core].[Log].[Title] like N'Error: (%' AND [Aqueduct].[Core].[Log].[LogTypeId]=(1)">
<Logical Operation="AND">
<ScalarOperator>
<Compare CompareOp="EQ">
<ScalarOperator>
<Intrinsic FunctionName="substring">
<ScalarOperator>
<Identifier>
<ColumnReference Database="[Aqueduct]" Schema="[Core]" Table="[Log]" Column="Title" />
</Identifier>
</ScalarOperator>
<ScalarOperator>
<Const ConstValue="(9)" />
</ScalarOperator>
<ScalarOperator>
<Arithmetic Operation="SUB">
<ScalarOperator>
<Intrinsic FunctionName="patindex">
<ScalarOperator>
<Const ConstValue="N'%)%'" />
</ScalarOperator>
<ScalarOperator>
<Identifier>
<ColumnReference Database="[Aqueduct]" Schema="[Core]" Table="[Log]" Column="Title" />
</Identifier>
</ScalarOperator>
</Intrinsic>
</ScalarOperator>
<ScalarOperator>
<Const ConstValue="(9)" />
</ScalarOperator>
</Arithmetic>
</ScalarOperator>
</Intrinsic>
</ScalarOperator>
<ScalarOperator>
<Const ConstValue="N'CheckHelpDeskEmail'" />
</ScalarOperator>
</Compare>
</ScalarOperator>
<ScalarOperator>
<Intrinsic FunctionName="like">
<ScalarOperator>
<Identifier>
<ColumnReference Database="[Aqueduct]" Schema="[Core]" Table="[Log]" Column="Title" />
</Identifier>
</ScalarOperator>
<ScalarOperator>
<Const ConstValue="N'Error: (%'" />
</ScalarOperator>
</Intrinsic>
</ScalarOperator>
<ScalarOperator>
<Compare CompareOp="EQ">
<ScalarOperator>
<Identifier>
<ColumnReference Database="[Aqueduct]" Schema="[Core]" Table="[Log]" Column="LogTypeId" />
</Identifier>
</ScalarOperator>
<ScalarOperator>
<Const ConstValue="(1)" />
</ScalarOperator>
</Compare>
</ScalarOperator>
</Logical>
</ScalarOperator>
</Predicate>
</Filter>
</RelOp>
</Parallelism>
</RelOp>
</ComputeScalar>
</RelOp>
</QueryPlan>
</StmtSimple>
</Statements>
</Batch>
</BatchSequence>
</ShowPlanXML>
答案 0 :(得分:4)
您的代码无效假设。在像SQL这样的声明性集合导向语言中,执行可以自由选择它认为合适的任何执行计划。您认为低效的内容很可能是有效的优化,其中标题首先从满足lastmodified
上的谓词或类似内容的索引进行投影。你不能对执行顺序做任何假设,因此不允许你在投影列表中有像SUBSTRING(..,9,..)那样会在某些行上轰炸的表达式。
由类似的无效假设引起的问题的另一个例子是SQL Server boolean operator short-circuit评估错误。