关于强制HASH语句报错,100分,解决马上给

周睿 2013-03-21 09:44:00
加精
问题描述,我在做SQL语句优化的时候发现使用HASH匹配,当时没有报错,可能条件不一样,,运行了一段时间发现报如下错误

SELECT COUNT(*)
FROM vcb_ContractGrid
LEFT JOIN ( SELECT DISTINCT
BusinessGUID
FROM vjd_Work2Business
WHERE Type = '合同'
AND BeginDateJh != ConfirmedBeginDate
) b ON vcb_ContractGrid.ContractGUID = b.BusinessGUID
WHERE vcb_ContractGrid.BUGUID = ( '993dcc44-7297-415f-9f4a-6c87e7f49387' )
AND vcb_ContractGrid.IfDdhs = 1
AND vcb_ContractGrid.IfConfirmFkPlan = 0
AND vcb_ContractGrid.JbrGUID = ( '39957769-229b-442e-b839-7ff710433c17' )
AND ( (( ( 1 = 1
AND ( JbDeptCode = 'zb.c1006'
OR JbDeptCode LIKE 'zb.c1006.%'
)
)
AND ( 1 = '1' )
)
AND ( 88 = 88 ))
)
AND ( ( vcb_ContractGrid.ContractGUID IN (
SELECT cb_ContractProj.ContractGUID
FROM cb_ContractProj
INNER HASH JOIN ( SELECT ContractGUID
FROM cb_Contract2HTType aa
INNER JOIN cb_ContractAction bb ON aa.HtTypeGUID = bb.RefGUID
AND ( bb.isView = 1 )
AND bb.BUGUID = '993dcc44-7297-415f-9f4a-6c87e7f49387'
AND aa.BUGUID = '993dcc44-7297-415f-9f4a-6c87e7f49387'
INNER JOIN MyUserToOrg ku2o ON bb.OrgGuid = ku2o.OrgGuid
AND ku2o.UserGUID = '39957769-229b-442e-b839-7ff710433c17'
) b ON b.ContractGUID = cb_ContractProj.ContractGUID
WHERE cb_ContractProj.ProjGUID IN (
'7e826468-fc51-44bd-a291-a8f5f5996848',
'490a5165-f4bc-4265-b5bb-4d4fd8d4c1c4',
'90a09346-9d7a-4746-a465-897655158e04',
'bf9593a2-af37-4a65-907b-395e13c1cac1',
'8e913ee3-e991-458d-8321-d9f76a3433d2',
'd314b067-603e-4691-a785-2cb384004c94',
'eaa6f096-9f6d-4f2b-87df-d95e44f42a5c',
'37327427-e1e5-4e56-bd87-62cb98bfb392',
'14e29305-1c19-492f-a6f9-cfb9c16cde8c',
'e6689bc2-8995-43cf-a497-561122bfea7f',
'b4243753-0d76-49d7-a22c-567022fc1188',
'bd69b6cf-5b30-462a-a485-bbdcd7ede872',
'839933cd-8669-4e30-bc76-0cbf5515b206',
'00000000-0000-0000-0000-000000000000' ) ) )
AND vcb_ContractGrid.ContractGUID = '9a11ee59-0345-4f3e-8c49-21474c95d980'
) ;




语句中HASH,对性能影响非常明显,但现在报错了

消息 8622,级别 16,状态 1,第 1 行
由于此查询中定义了提示,查询处理器未能生成查询计划。请重新提交查询,并且不要在查询中指定任何提示,也不要使用 SET FORCEPLAN。


错误如下,后来吧HASH放到INNER JOIN cb_ContractAction 中间问题解决,但不知道是什么原因造成的,为什么报错,请专家解释原理。
...全文
3799 83 打赏 收藏 转发到动态 举报
写回复
用AI写文章
83 条回复
切换为时间正序
请发表友善的回复…
发表回复
chris_young 2014-01-02
  • 打赏
  • 举报
回复
一边结果集为空,就报错了吧?
lcmqwe 2013-03-28
  • 打赏
  • 举报
回复
lcmqwe 2013-03-28
  • 打赏
  • 举报
回复
论坛楼主csdn都给力
秀男 2013-03-26
  • 打赏
  • 举报
回复
不错,试试看
LongRui888 2013-03-22
  • 打赏
  • 举报
回复
另外,说实在很多时候,由于工作比较忙,要是碰到这种无法生成执行计划的问题,一般就会避开或者绕过这个问题,我觉得你这种探索问题的精神真的值得大家学习。 不过探究这种问题最后不一定能得到什么结论,你很难知道到底是什么原因导致的问题,只能通过猜测,并且修改语句来做各种测试,来验证自己的猜测,就算验证了猜测,这个也只是猜测,而且可能只是在某些SQL Server的版本下有用,等版本一升级,可能优化器的行为就变化了,就跟你在研究一个古林精怪的人一样,你在研究他的脾气秉性,你可能能知道在什么情况下,他会有什么行为,但这些都是在严格的条件或者限制下才能有用的。 另外,可能SQL Server优化器的开发人员,在解决SQL优化问题的同时,导致了一个没有想到的结果,他也不知道你会写这么复杂的语句,他也没想到他自己写的优化器会产生这样的问题。
LongRui888 2013-03-22
  • 打赏
  • 举报
回复
之前我也遇到过类似的问题,确实加上hash之后,性能提升很大,但是由于查询条件的不确定性,也就是where后面可以加很多不同的查询条件,同时会有不同的值,所以偶尔会报错,最后通过把整个非常复杂的语句拆分成小的语句,然后把中间结果集插入到临时表中,最后再从临时表中取数,数据量也有几千万条,如果你要加快速度,建议再加个索引。 另外,你上面的问题,从表面看,你的语句里在用hash的地方确实用的等于谓词,照理应该不会导致无法生成执行计划,大家从表面上看很难知道到底是什么原因导致无法生成执行计划,可能是bug问题,可能是语句写法有问题、索引、统计信息等问题导致的,可能只要改变其中一个影响生成执行计划的因素,就能影响优化器,产生能实际执行的执行计划了。 以前,我写语句也是大量的加merge,hash查询提示,甚至不仅是对表join,对union和group,也加了,但这些提示非常难以控制,也就是效果不一定稳定,要想达到比较稳定的效果,必须让运维定时更新统计信息,以及进行必要的碎片整理,这样才是长久之计。
  • 打赏
  • 举报
回复
为了严谨性,我问了一下 query optimizer development team的 developer lead,他这么回答我的“What you say is correct. Starting with SQL Server 2012, the optimizer adds back the redundant predicate so that it can honor the hash join (or merge join) hint.”
周睿 2013-03-22
  • 打赏
  • 举报
回复
还有高手来解题么?没有今天就结贴了
周睿 2013-03-22
  • 打赏
  • 举报
回复
引用 73 楼 SQL_Beginner 的回复:
为了严谨性,我问了一下 query optimizer development team的 developer lead,他这么回答我的“What you say is correct. Starting with SQL Server 2012, the optimizer adds back the redundant predicate so that it ca……
其实至少说明了,这种强关联方式在2012中是可以放心使用了
張晓亞 2013-03-22
  • 打赏
  • 举报
回复
几乎我看过的书上都说,hint,要慎用,今天的高效可能就是明天的灾难。取消掉吧。保证统计信息更新及时的前提下,让SQLServer自己去决定关联方式。
就这样来咯 2013-03-22
  • 打赏
  • 举报
回复
不错 加油 支持一欧啊
發糞塗牆 2013-03-21
  • 打赏
  • 举报
回复
这跟in有关系,当in过于多的时候,执行计划就容易无法生成,因为可能的执行计划非常多。
周睿 2013-03-21
  • 打赏
  • 举报
回复
引用 19 楼 DBA_Huangzj 的回复:
貌似有点头绪了,你试下把你顶楼那个原始语句中的in,改写成exists,其他不改动
是的这样确实不报错了,原因呢??
爱克微尔 2013-03-21
  • 打赏
  • 举报
回复
貌似没有问题啊
發糞塗牆 2013-03-21
  • 打赏
  • 举报
回复
貌似有点头绪了,你试下把你顶楼那个原始语句中的in,改写成exists,其他不改动
周睿 2013-03-21
  • 打赏
  • 举报
回复
引用 17 楼 DBA_Huangzj 的回复:
试试:我把你的count(*)改了count(1),没必要验证所有列,不过你测试一下数据SQL code?123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354SET FORCEPLAN ON ; SELECT COUNT(1)……
已经测试,不行,错误一样
發糞塗牆 2013-03-21
  • 打赏
  • 举报
回复
试试:我把你的count(*)改了count(1),没必要验证所有列,不过你测试一下数据
SET FORCEPLAN ON ;

SELECT  COUNT(1)
FROM    vcb_ContractGrid
        LEFT JOIN ( SELECT DISTINCT
                            BusinessGUID
                    FROM    vjd_Work2Business
                    WHERE   Type = '合同'
                            AND BeginDateJh != ConfirmedBeginDate
                  ) b ON vcb_ContractGrid.ContractGUID = b.BusinessGUID
WHERE   vcb_ContractGrid.BUGUID = ( '993dcc44-7297-415f-9f4a-6c87e7f49387' )
        AND vcb_ContractGrid.IfDdhs = 1
        AND vcb_ContractGrid.IfConfirmFkPlan = 0
        AND vcb_ContractGrid.JbrGUID = ( '39957769-229b-442e-b839-7ff710433c17' )
        AND ( (( ( 1 = 1
                   AND ( JbDeptCode = 'zb.c1006'
                         OR JbDeptCode LIKE 'zb.c1006.%'
                       )
                 )
                 AND ( 1 = '1' )
               )
              AND ( 88 = 88 ))
            )
        AND ( ( vcb_ContractGrid.ContractGUID IN (
                SELECT  cb_ContractProj.ContractGUID
                FROM    cb_ContractProj
                        INNER HASH  JOIN ( SELECT   ContractGUID
                                           FROM     cb_Contract2HTType aa
                                                    INNER  JOIN cb_ContractAction bb ON aa.HtTypeGUID = bb.RefGUID
                                                              AND ( bb.isView = 1 )
                                                              AND bb.BUGUID = '993dcc44-7297-415f-9f4a-6c87e7f49387'
                                                              AND aa.BUGUID = '993dcc44-7297-415f-9f4a-6c87e7f49387'
                                                    INNER JOIN MyUserToOrg ku2o ON bb.OrgGuid = ku2o.OrgGuid
                                                              AND ku2o.UserGUID = '39957769-229b-442e-b839-7ff710433c17'
                                         ) b ON b.ContractGUID = cb_ContractProj.ContractGUID
                WHERE   cb_ContractProj.ProjGUID IN (
                        '7e826468-fc51-44bd-a291-a8f5f5996848',
                        '490a5165-f4bc-4265-b5bb-4d4fd8d4c1c4',
                        '90a09346-9d7a-4746-a465-897655158e04',
                        'bf9593a2-af37-4a65-907b-395e13c1cac1',
                        '8e913ee3-e991-458d-8321-d9f76a3433d2',
                        'd314b067-603e-4691-a785-2cb384004c94',
                        'eaa6f096-9f6d-4f2b-87df-d95e44f42a5c',
                        '37327427-e1e5-4e56-bd87-62cb98bfb392',
                        '14e29305-1c19-492f-a6f9-cfb9c16cde8c',
                        'e6689bc2-8995-43cf-a497-561122bfea7f',
                        'b4243753-0d76-49d7-a22c-567022fc1188',
                        'bd69b6cf-5b30-462a-a485-bbdcd7ede872',
                        '839933cd-8669-4e30-bc76-0cbf5515b206',
                        '00000000-0000-0000-0000-000000000000' ) ) )
              AND vcb_ContractGrid.ContractGUID = '9a11ee59-0345-4f3e-8c49-21474c95d980'
            ) ; 
            
SET FORCEPLAN OFF ;
周睿 2013-03-21
  • 打赏
  • 举报
回复
没有加过SET FORCEPLAN,不报错即可
發糞塗牆 2013-03-21
  • 打赏
  • 举报
回复
那按照它的提示,你有没有试过加:SET FORCEPLAN 你是想不抱错?还是想优化?
周睿 2013-03-21
  • 打赏
  • 举报
回复
引用 13 楼 DBA_Huangzj 的回复:
非要用的话试试改成这个:OPTION (HASH JOIN);
这是一样的结果,使用OPTION (HASH JOIN);是说明,SQL语句中所有的连接全部使用HASH 的方式
加载更多回复(56)

22,210

社区成员

发帖
与我相关
我的任务
社区描述
MS-SQL Server 疑难问题
社区管理员
  • 疑难问题社区
  • 尘觉
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧