Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/72.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用或条件+;join中的函数似乎混淆了SQL Server';s查询优化器_Sql_Sql Server - Fatal编程技术网

使用或条件+;join中的函数似乎混淆了SQL Server';s查询优化器

使用或条件+;join中的函数似乎混淆了SQL Server';s查询优化器,sql,sql-server,Sql,Sql Server,我正在努力调试特定查询的性能。问题是: select count(*) FROM dbo.user d INNER JOIN dbo.distinct_first_name dfn ON ( [dbo].jw(dfn.first_name, 'john') > 0.8 AND (d.first_name = dfn.first_name OR d.nick_name = dfn.first_name O

我正在努力调试特定查询的性能。问题是:

select count(*)  
FROM dbo.user d
INNER JOIN dbo.distinct_first_name dfn ON (
        [dbo].jw(dfn.first_name, 'john') > 0.8
        AND
        (d.first_name = dfn.first_name
         OR d.nick_name = dfn.first_name
         OR d.middle_name = dfn.first_name)
        )
该查询在一个不同的名字表(包含大约15k行)上运行一个Jaro Winkler过滤器,然后将其与用户表进行内部连接以生成结果集。根据定义,运行用户表中约500k行大约需要1分钟

以下是我所知道的:

1) Jaro Winkler过滤器几乎是即时的(自身为0.1s)

2) 如果我将user子句更改为仅包含一列(即删除ORs),则只需0.4s

3) 如果我将此更改为三个查询,并背靠背运行它们,大约需要2秒

4) 如果我将Jaro Winkler过滤器更改为0.99(因此只有一个结果),则查询执行时间没有实质性差异

5) 如果我用相等操作(dfn.first_name='john')替换Jaro Winkler过滤器,则总查询时间将减少到4s

(所有计时都相当缓慢;现实生活中的表现会更好。)

因此,出于某种原因,函数和ORs的组合使查询优化器感到困惑。执行计划信息量不大;它说90%的查询用于:

<RelOp NodeId="63" PhysicalOp="Clustered Index Seek" LogicalOp="Clustered Index Seek" EstimateRows="1.69029" EstimateIO="0.003125" EstimateCPU="0.000158859" AvgRowSize="17" EstimatedTotalSubtreeCost="71.4311" TableCardinality="15958" Parallel="0" EstimateRebinds="448881" EstimateRewinds="0.504024" EstimatedExecutionMode="Row">
                              <OutputList>
                                <ColumnReference Database="[mydb]" Schema="[dbo]" Table="[distinct_first_name]" Alias="[dfn]" Column="first_name" />
                              </OutputList>
                              <RunTimeInformation>
                                <RunTimeCountersPerThread Thread="0" ActualRows="857936" ActualEndOfScans="859454" ActualExecutions="859454" />
                              </RunTimeInformation>
                              <IndexScan Ordered="1" ScanDirection="FORWARD" ForcedIndex="0" ForceSeek="0" ForceScan="0" NoExpandHint="0" Storage="RowStore">


将查询拆分实际上是一种选择,因为这是一个存储过程,我可能会重新设计一点模式,但我很难说是什么让它陷入困境。有什么想法吗?

一些你可能想尝试的事情:

  • dfn表的聚集索引是什么?这只是一张有名字的桌子吗?如果是,请删除“自动编号”列(如果有的话),并将该名称作为聚集索引

  • “约翰”是你狂欢的理由吗?我想是的。您可以首先在两个名称数据集中最小的数据集上计算Jaro Winkler过滤器,并将其插入到临时表中。然后连接临时表上的另一个表。请记住,临时表也可以从索引中获益(如果您添加索引的话)

  • 您可以通过创建多列索引来提高性能:名字、昵称、中间名。由于where语句中引用的所有列,单个索引的有用性会降低

  • 我认为运行SQL Tuning advisor工具并查看它提供了什么样的建议总是很有趣的。只需将监视器附加到SQL server实例,并将查询的执行情况记录到工作负载文件中即可。然后,您可以将工作负载文件提供给advisor工具,如果启用该选项,它将建议索引、统计信息甚至模式更改

  • 尽可能预先计算。如果我没记错的话,在Jaro Winkler过滤器中,字符串长度是一个重要因素。您可以使用名称的字符串长度向dfn表中添加一列。函数和视图之类的东西很好,但不一定是性能最好的。该函数就像一个黑匣子,无法利用任何预先存在或预先计算的数据

最重要的是:衡量你的结果。SQL查询优化器有自己的想法。关注执行计划并尝试不同的场景


基于文本列的查询总是更难优化。您可能希望查看全文索引以进一步提高性能,但这是一个单独的主题需要研究。

您可能希望尝试的一些事情:

  • dfn表的聚集索引是什么?这只是一张有名字的桌子吗?如果是,请删除“自动编号”列(如果有的话),并将该名称作为聚集索引

  • “约翰”是你狂欢的理由吗?我想是的。您可以首先在两个名称数据集中最小的数据集上计算Jaro Winkler过滤器,并将其插入到临时表中。然后连接临时表上的另一个表。请记住,临时表也可以从索引中获益(如果您添加索引的话)

  • 您可以通过创建多列索引来提高性能:名字、昵称、中间名。由于where语句中引用的所有列,单个索引的有用性会降低

  • 我认为运行SQL Tuning advisor工具并查看它提供了什么样的建议总是很有趣的。只需将监视器附加到SQL server实例,并将查询的执行情况记录到工作负载文件中即可。然后,您可以将工作负载文件提供给advisor工具,如果启用该选项,它将建议索引、统计信息甚至模式更改

  • 尽可能预先计算。如果我没记错的话,在Jaro Winkler过滤器中,字符串长度是一个重要因素。您可以使用名称的字符串长度向dfn表中添加一列。函数和视图之类的东西很好,但不一定是性能最好的。该函数就像一个黑匣子,无法利用任何预先存在或预先计算的数据

最重要的是:衡量你的结果。SQL查询优化器有自己的想法。关注执行计划并尝试不同的场景


基于文本列的查询总是更难优化。您可能希望查看全文索引以进一步提高性能,但这是一个单独的主题需要研究。

您可能希望尝试的一些事情:

  • dfn表的聚集索引是什么?这只是一张有名字的桌子吗?如果是,请删除“自动编号”列(如果有的话),并将该名称作为聚集索引

  • “约翰”是一个论点吗