基数在SQLServer中的where子句中使用函数(IS_MEMBER)时估计警告

时间:2017-08-25 07:43:22

标签: sql-server sql-server-2012 type-conversion sql-execution-plan

考虑以下情景

测试数据

CREATE TABLE   T1 (
     COL1   numeric (6, 0) NOT NULL,
     COL2   numeric (18, 0) NOT NULL,
     COL3   numeric (18, 0) NOT NULL,
     COL4   numeric (5, 0) NOT NULL,
     COL5   numeric (18, 0) NOT NULL,
     COL6   varchar (20) NOT NULL,
     COL7   varchar (50) NULL,
     COL8   numeric (1, 0) NULL,
     COL9   numeric (18, 0) NULL,
     COL10   varchar (20) NULL 
 ) 

ALTER TABLE  T1    
ADD PRIMARY KEY ( COL1,COL2, COL3,  COL4,  COL5, COL6    )

INSERT INTO  T1 VALUES (1,  2,  12, 1,  11, 'COL_1',    '000002',   0,  NULL,   'admin_group')

INSERT INTO  T1 VALUES (1,  2,  12, 1,  11, 'COL_2',    '000002',   0,  NULL,   'admin_group')

INSERT INTO  T1 VALUES (1,  2,  12, 1,  11, 'COL_3',    '000002',   0,  NULL,   'QABrowns')

INSERT INTO  T1 VALUES (1,  2,  12, 1,  11, 'COL_4',    '000002',   0,  NULL,   'QABrowns')

INSERT INTO  T1 VALUES (1,  2,  12, 1,  11, 'COL_5',    '000002',   0,  NULL,   'QABrowns')

INSERT INTO  T1 VALUES (1,  2,  12, 1,  11, 'COL_6',    '000002',   0,  NULL,   'QABrowns')

INSERT INTO  T1 VALUES (1,  2,  12, 1,  11, 'COL_7',    '000002',   0,  NULL,   'QABrowns')

INSERT INTO  T1 VALUES (1,  2,  12, 1,  11, 'COL_8',    '000002',   0,  NULL,   'SuperUser')

INSERT INTO  T1 VALUES (1,  2,  12, 1,  11, 'COL_9',    '000002',   0,  NULL,   'SuperUser')

INSERT INTO  T1 VALUES (1,  2,  12, 1,  11, 'COL_10',   '000002',   0,  NULL,   'SuperUser')

INSERT INTO  T1 VALUES (1,  2,  12, 1,  11, 'COL_11',   '000002',   0,  NULL,   'LOLCOP2')

INSERT INTO  T1 VALUES (1,  2,  12, 1,  11, 'COL_12',   '000002',   0,  NULL,   'LOLCOP2')

INSERT INTO  T1 VALUES (1,  2,  12, 1,  11, 'COL_13',   '000002',   0,  NULL,   'LOLCOP2')

INSERT INTO  T1 VALUES (1,  2,  12, 1,  11, 'COL_14',   '000002',   0,  NULL,   'LOLCOP2')

情景1:

 SELECT T1.* from  T1 
    WHERE IS_MEMBER( COL10)=1 

- 执行计划警告 -

  

“表达式(CONVERT_IMPLICIT(nvarchar(20),[V9WEBDB1].[V9WEBDB1].[T3].[COL10],0)) may affect "CardinalityEstimate" in query plan choice"

中的类型转换

场景2

SELECT * INTO  T3  FROM  T1 WHERE COL10 IN ('admin_group')
ALTER TABLE  T3    
ADD PRIMARY KEY ( COL1,COL2, COL3,  COL4,  COL5, COL6    )
UPDATE STATISTICS  T3   
INSERT INTO  T3 SELECT * FROM  T1 WHERE COL10 IN ('LOLCOP2','QABrowns','SuperUser')

UPDATE STATISTICS  T3

SELECT T3.* from  T3 
WHERE IS_MEMBER( COL10)=1 

- 执行计划警告:

  

“表达式中的类型转换(CONVERT_IMPLICIT(nvarchar(20),[V9WEBDB1]。[V9WEBDB1]。[T3]。[COL10],0))可能影响查询计划选择中的”CardinalityEstimate“”

场景3

SELECT * INTO  T4  FROM  T1 WHERE COL10 IN ('admin_group')
ALTER TABLE  T4    
ADD PRIMARY KEY ( COL1,COL2, COL3,  COL4,  COL5, COL6    )

UPDATE STATISTICS  T4   

SELECT T4.* from  T4 
WHERE IS_MEMBER( COL10)=1 

执行计划警告 - 无

INSERT INTO  T4 SELECT * FROM  T1 WHERE COL10 IN ('LOLCOP2','QABrowns','SuperUser')

UPDATE STATISTICS  T4 

SELECT T4.* from  T4 
WHERE IS_MEMBER( COL10)=1 

执行计划警告 - 无

问:

在第一和第二场景中

SELECT T1.* from  T1 WHERE IS_MEMBER( COL10)=1 

sql发出以下警告

  

“表达式中的类型转换(CONVERT_IMPLICIT(nvarchar(20),[V9WEBDB1]。[V9WEBDB1]。[T3]。[COL10],0))可能影响查询计划选择中的”CardinalityEstimate“”

但是在第三种情况中

SELECT T1.* from  T1 WHERE IS_MEMBER( COL10)=1 

sql没有给出任何警告。

COL10的数据类型是varchar(20)。

服务器整理: SQL_Latin1_General_CP1_CI_AS

1)为什么会出现这种警告? 2)如何避免上述警告?

1 个答案:

答案 0 :(得分:1)

  

1)为什么会出现这种警告?

您的表格列col10varchar(20),但IS_MEMBER()接受sysname作为参数,因此服务器会将您的varchar(20)转换为nvarchar(20)sysnamenvarchar(128)

  

2)如何避免上述警告?

将您的col10类型更改为sysname或至少更改为nvarchar(20)