代码之家  ›  专栏  ›  技术社区  ›  Matt

索引以检查一个非常大的表在某一列中是否包含精确的字符串

  •  1
  • Matt  · 技术社区  · 6 年前

    CREATE TABLE [dbo].[TestDefinition]
    (
        [Id] [int] IDENTITY(1,1) NOT NULL,
        [Name] [varchar](500) NOT NULL,
        [TeamId] [int] NOT NULL,
    
        CONSTRAINT [PK_Test] 
            PRIMARY KEY CLUSTERED ([Id] ASC)
    ) ON [PRIMARY]
    GO
    

    我想在表中插入新记录,但首先我需要确保该记录不存在。

    我基本上是用这些值构建一个表( @TestDefinitionInput -一个TVP)我想插入,然后我把它传递到一个存储过程中。

    WITH W AS 
    (
       SELECT [Name], TeamId
       FROM @TestDefinitionInput
    ),
    X AS 
    (
       SELECT W.* 
       FROM W
       LEFT JOIN TestDefinition td ON td.TeamId = W.TeamId AND td.[Name] = W.[Name] 
       WHERE td.Id IS NULL
    )
    INSERT INTO TestDefinition ([Name], [TeamId]) 
       SELECT [Name], [TeamId]
       FROM X;
    

    我的问题是这是一个有5亿行的Sloow。我真的不是很精通SQL,我想知道我应该如何,如果我应该,索引 dbo.[TestDefinition] 尽快完成。

    1 回复  |  直到 6 年前
        1
  •  2
  •   Mitch Wheat    6 年前

    你有几种可能:

    CONSTRAINT [PK_Test] 
        PRIMARY KEY CLUSTERED (TeamId ASC, [Id] ASC)
    

    以扩展附加到主键的聚集索引为代价,您不会在标识列上烧录范围搜索索引。这将需要定期碎片整理

    另一个( )选项是创建非聚集索引:

    CREATE INDEX IX_TestDefinition_TeamId_Name 
        ON dbo.TestDefinition(TeamId, Name)
    

    Id 因为它是聚类键,并且添加到每个非聚类索引。]

    我还会考虑将传入的TVP参数值放入临时表而不是表变量中,并连接到该表(甚至在其上创建相应的索引)。表变量因基数估计差而臭名昭著。

    .... with (data_compression = page);
    

    Data compression 不是在每个版本的SQL Server中都可用。SQL Server 2016以后的版本是标准版。