sql-server-2008 – SQL Server中“无连接谓词”究竟是什么意思?

前端之家收集整理的这篇文章主要介绍了sql-server-2008 – SQL Server中“无连接谓词”究竟是什么意思?前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
MSDN“ Missing Join Predicate Event Class”表示它“表示正在执行的查询没有连接谓词”.

但不幸的是,它似乎并不那么容易.

例如,非常简单的情况:

create table #temp1(i int);
create table #temp2(i int);
Select * from #temp1,#temp2 option (recompile);

表中没有数据,也没有警告,尽管它显然没有连接谓词.

如果我查看sql Server 2005的文档(相同的链接,只是其他服务器版本),还有一个额外的句子:“仅当连接的两端返回多行时才会生成此事件.”这在以前的情况下会非常有意义.没有数据,因此双方都返回0行而没有警告.插入行,得到警告.好的.

但是对于下一个令人困惑的情况,我在两个表中插入相同的值:

Insert into #temp1 (i) values (1)
Insert into #temp1 (i) values (1)
Insert into #temp2 (i) values (1)
Insert into #temp2 (i) values (1)

我得到:

-- no warning:
Select * from #temp1 t1 
    inner join #temp2 t2 on t1.i = t2.i 
option (recompile)
-- has warning:
Select * from #temp1 t1 
    inner join (select 1 i union all select 1) t2 on t1.i = t2.i 
option (recompile)

为什么会这样?

注意:我用来检测服务器上的这些错误查询的一些脚本.

>当然,程序的执行计划
>使用默认服务器跟踪查找警告

Declare @trace nvarchar(500);
Select @trace = cast(value as nvarchar(500))
From sys.fn_trace_getinfo(Null)
Where traceid = 1 and property = 2;

Select t.StartTime,te.name,*
From sys.fn_trace_gettable(@trace,1) t
    Inner join sys.trace_events te on t.EventClass = te.trace_event_id
    where EventClass = 80
order by t.StartTime desc

>执行计划缓存,找到那些有警告的计划(比如这个)

WITH XMLNAMESPACES (default 'http://schemas.microsoft.com/sqlserver/2004/07/showplan')
SELECT
    Cast('<?sql ' + st.text + ' ?>' as xml) sql_text,pl.query_plan,ps.execution_count,ps.last_execution_time,ps.last_elapsed_time,ps.last_logical_reads,ps.last_logical_writes
FROM sys.dm_exec_query_stats ps with (NOLOCK)
    Cross Apply sys.dm_exec_sql_text(ps.sql_handle) st
    Cross Apply sys.dm_exec_query_plan(ps.plan_handle) pl
WHERE pl.query_plan.value('(//Warnings/@NoJoinPredicate)[1]','bit') = 1
Order By last_execution_time desc
OPTION (RECOMPILE);

解决方法

您的问题与 this one类似.有时,sql Server可以从原始查询删除连接谓词.

如果您看到sql Server在编译时检测到连接谓词警告,则常量表只有一个不同的值且该值为1,因此将查询重写为

SELECT *
FROM   (SELECT *
        FROM   #temp1 t1
        WHERE  t1.i = 1) t1
       CROSS JOIN (SELECT 1 i
                   UNION ALL
                   SELECT 1) t2

#temp的表扫描有一个谓词如下[tempdb].[dbo].[#temp1].[i] =(1)

在使用两个表时,如果常量表包含多个不同的值,则无法在编译时以这种方式删除on t1.i = t2.i的连接谓词.

有关这方面的更多信息,请参见Paul WhiteQuery Optimizer Deep Dive系列.

猜你在找的MsSQL相关文章