记一次alwayson主从执行计划不一致

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/weixin_38357227/article/details/88551131

前几天有生产人员反馈:同一个SQL语句,在从库可以正常执行,在主库上执行就报错。
具体的sql语句如下:

select DISTINCT convert(date,SUBSTRING(TEST_ID,9,8)) AA, 
SURVEY_DATE from test1
where QA=1
and convert(date,SUBSTRING(TEST_ID,9,8))<>convert (date,SURVEY_DATE)
and convert (date,SURVEY_DATE)>'2017-01-01' 
order by SURVEY_DATE desc

报错信息为:
消息 241,级别 16,状态 1,第 1 行
从字符串转换日期和/或时间时,转换失败。
经验证,为主从库执行计划不一致导致。更新主库该表的统计信息后,查询正确。
下面为详细分析:
该查询在主库的执行计划:
主库的执行计划索引扫描键查找
按照执行计划从右向左,从上至下的阅读顺序,可以看到该查询
1.先进行[test1$BPK_AK_Key]索引扫描,筛选出符合convert(date,SUBSTRING(TEST_ID,9,8))<>convert (date,SURVEY_DATE) and convert (date,SURVEY_DATE)>‘2017-01-01’ 的数据

2.通过聚集索引PK__test1__3214EC2752D1D5B7进行键查找操作,筛选出QA=1的数据

查看该表表结构:
在这里插入图片描述查看该查询数据:
test表数据
根据上述信息基本可以判断出报错原因:
由于先走[test1$BPK_AK_Key]索引扫描,导致全表数据都需要经过

convert(date,SUBSTRING(TEST_ID,9,8))<>convert (date,SURVEY_DATE)
and convert (date,SURVEY_DATE)>'2017-01-01’

条件筛选。而经过SUBSTRING(TEST_ID,9,8)运算后,有部分值中含有英文字母,导致convert (date)失败。因此SQL报错。

该查询在从库的执行计划:
从库的执行计划在这里插入图片描述
在从库上直接进行聚集索引扫描,根据SQL中列出的条件进行判断输出。
由此可推断出,主库执行报错,主要是因为数据库选择了不合适的执行计划导致的。那么这种问题应该如何纠正呢。
执行计划的选择主要是根据统计信息确定的。执行计划出问题,首先想到可能是统计信息的问题。
先更新该表的统计信息:

UPDATE STATISTICS dbo.test WITH FULLSCAN;

在主库上重新执行该查询,成功,无报错。
问题解决

下面是涉及统计信息的常用查询:

 --查询表的具体的统计信息
    DBCC SHOW_STATISTICS('Table_Name','Statistics_name')
 --手动创建统计信息
    CREATE STATISTICS nameON dbo.Table_Name(Column_Name)
 --查询统计信息最后更新时间
    SELECT 
        Object_name = OBJECT_NAME(object_id)
        ,Stats_Name = [name]
        ,Stats_Last_Updated = STATS_DATE([object_id], [stats_id])
    FROM sys.stats WITH(NOLOCK)

在这里插入图片描述

--更新统计信息
--更新索引级别
UPDATE STATISTICS dbo.Table_Name Index_Name;
--更新表级别
UPDATE STATISTICS dbo.Table_Name WITH FULLSCAN;
--更新库级别
EXEC sys.sp_updatestats

更详细的统计信息知识可点击:SQL Server幕后英雄 - 统计信息

猜你喜欢

转载自blog.csdn.net/weixin_38357227/article/details/88551131