如何改进此查询以避免哈希匹配

时间:2013-11-02 00:01:30

标签: sql sql-execution-plan

我有q查询来选择重复行的ID。如果provinceID相同且至少有一个phonenumber相同,那么我们可以确定两行是同一个。

SELECT i1.ID 
            FROM pigeon.dbo.Instrument i1
            WHERE EXISTS(
                SELECT i2.ID 
                FROM pigeon.dbo.Instrument i2
                WHERE i2.ID != i1.ID and i2.ProvinceID = i1.ProvinceID and
                (
                    (RTRIM(i2.PhoneNumber1) != '' and (RTRIM(i2.PhoneNumber1) = RTRIM(i1.PhoneNumber1) or RTRIM(i2.PhoneNumber1) = RTRIM(i1.PhoneNumber2) or RTRIM(i2.PhoneNumber1) = RTRIM(i1.PhoneNumber3))) or
                    (RTRIM(i2.PhoneNumber2) != '' and (RTRIM(i2.PhoneNumber2) = RTRIM(i1.PhoneNumber1) or RTRIM(i2.PhoneNumber2) = RTRIM(i1.PhoneNumber2) or RTRIM(i2.PhoneNumber2) = RTRIM(i1.PhoneNumber3))) or 
                    (RTRIM(i2.PhoneNumber3) != '' and (RTRIM(i2.PhoneNumber3) = RTRIM(i1.PhoneNumber1) or RTRIM(i2.PhoneNumber3) = RTRIM(i1.PhoneNumber2) or RTRIM(i2.PhoneNumber3) = RTRIM(i1.PhoneNumber3)))
                )           
            )

查询执行计划

enter image description here

虽然其他类似的查询执行得非常好,并且执行计划中没有哈希匹配。查询是

SELECT i1.ID 
            FROM pigeon.dbo.Instrument i1
            WHERE EXISTS(
                SELECT i2.ID 
                FROM pigeon.dbo.Instrument i2
                WHERE i2.ID != i1.ID and i2.Name = i1.Name and 
                (
                    (RTRIM(i2.PhoneNumber1) != '' and (RTRIM(i2.PhoneNumber1) = RTRIM(i1.PhoneNumber1) or RTRIM(i2.PhoneNumber1) = RTRIM(i1.PhoneNumber2) or RTRIM(i2.PhoneNumber1) = RTRIM(i1.PhoneNumber3))) or
                    (RTRIM(i2.PhoneNumber2) != '' and (RTRIM(i2.PhoneNumber2) = RTRIM(i1.PhoneNumber1) or RTRIM(i2.PhoneNumber2) = RTRIM(i1.PhoneNumber2) or RTRIM(i2.PhoneNumber2) = RTRIM(i1.PhoneNumber3))) or 
                    (RTRIM(i2.PhoneNumber3) != '' and (RTRIM(i2.PhoneNumber3) = RTRIM(i1.PhoneNumber1) or RTRIM(i2.PhoneNumber3) = RTRIM(i1.PhoneNumber2) or RTRIM(i2.PhoneNumber3) = RTRIM(i1.PhoneNumber3)))
                )
            )

执行计划是

enter image description here

我为where子句中包含的所有字段创建了索引。

enter image description here

该表定义为

CREATE TABLE [dbo].[Instrument](
[ID] [bigint] IDENTITY(1,1) NOT NULL,
[Name] [nvarchar](250) NOT NULL,
[Gender] [char](1) NULL,
[Birthdate] [datetime] NULL,
[PhoneNumber1] [nvarchar](50) NULL,
[PhoneNumber2] [nvarchar](50) NULL,
[PhoneNumber3] [nvarchar](50) NULL,
[Email] [nvarchar](64) NULL,
[Address] [nvarchar](250) NULL,
[IDType] [smallint] NOT NULL,
[IDNumber] [nchar](32) NULL,
[ProvinceID] [char](16) NOT NULL,
[CityID] [char](16) NOT NULL,
[Blacklist] [bit] NULL,
[BeenProject] [nvarchar](64) NULL,
[BeenCity] [nvarchar](50) NULL,
[BeenDate] [datetime] NULL,
[BeenRemark] [nvarchar](250) NULL,
[PlateType] [smallint] NOT NULL,
[PlateNumber] [nchar](16) NULL,
[Color] [nchar](16) NULL,
[Vendor] [nvarchar](64) NULL,
[ModelID] [bigint] NOT NULL,
[Version] [nvarchar](64) NULL,
[Level] [nvarchar](64) NULL,
[ModelEx] [nvarchar](250) NULL,
[Van] [nvarchar](64) NULL,
[Volume] [nvarchar](64) NULL,
[EngineNumber] [nvarchar](64) NULL,
[VINNumber] [nvarchar](64) NULL,
[ShipmentDate] [datetime] NULL,
[BoughtDate] [datetime] NULL,
[RegisteDate] [datetime] NULL,
[Remark1] [nvarchar](500) NULL,
[Remark2] [nvarchar](500) NULL,
[Remark3] [nvarchar](500) NULL,
[Remark4] [nvarchar](500) NULL,
[Remark5] [nvarchar](500) NULL,
[Referer] [nvarchar](64) NULL,
[Shared] [bit] NOT NULL,
[Counter] [smallint] NOT NULL,
[XRefID] [bigint] NULL,
[Active] [bit] NOT NULL,
[CreatedBy] [nchar](32) NOT NULL,
[CreatedAt] [datetime] NOT NULL,
[UpdatedBy] [nchar](32) NULL,
[UpdatedAt] [datetime] NULL

为什么他们的执行计划如此不同?与第一个查询相比,第二个查询的性能非常好。请帮助改善第一个查询的性能。

0 个答案:

没有答案