使用非集群 GUID 主键并发插入 table

Concurrent inserts into table with non-clustered GUID primary key

我在 Microsoft SQL Server 2012 上有这个 table:

CREATE TABLE [dbo].[Addresses_line_format]
(
    address_id UNIQUEIDENTIFIER NOT NULL
        CONSTRAINT pk_addresses_line_format PRIMARY KEY NONCLUSTERED,

    country_id UNIQUEIDENTIFIER NOT NULL
        CONSTRAINT fk_address_single_line_country FOREIGN KEY REFERENCES Countries (country_id)
            ON UPDATE NO ACTION
            ON DELETE NO ACTION,

    address_line NVARCHAR(255) NOT NULL,
    district_line NVARCHAR(255) NOT NULL
)

其中有 3.362.817 条记录。

我们的应用程序使用队列中的消息,有 10 个并发使用者。每个消费者使用以下语句在此 table 中插入一行:

INSERT [dbo].[Addresses_line_format] ([address_id], [country_id], [address_line], [district_line])
VALUES (@0, @1, @2, @3)

查看统计信息,此查询的平均耗时为 16 秒,这显然太多了。

我想知道这是否是因为堆 table 处理插入的方式如所描述的那样 here,或者您是否知道造成这种情况的原因?

我尝试将 PK 更改为集群,但没有任何明显的性能改进。

针对 table 的查询始终使用以下内容执行:

SELECT country_id, address_line, district_line
FROM Addresses_line_format
WHERE address_id = @1

好吧,如果那个 GUID 不是聚集键 - table 上的聚集键是什么?它应该有一个 - 一个精心选择的聚集键加速操作 - 甚至插入和删除!请参阅 Kimberly Tripp 的博客 post The Clustered Index Debate Continues... 以获得详细解释和更多背景知识。

当您阅读 Kim Tripp 的博客 post 和她关于该主题的所有其他文章时,很明显,一个好的聚类键是窄的、唯一的、静态的并且不断增加 - 非常适合 INTBIGINT 标识列。

SQL 服务器的早期版本(2000 年或 2005 年之前)实际上确实有 插入热点 如果所有插入都发生在一个点 - 这些负面影响已被删除,这些不再是问题,因此,使用 INT IDENTITY 列作为您的聚簇键在大多数情况下几乎是最佳选择。

一行 16 秒太多了。从这个问题的严重程度来看,这不是坏索引键或太多索引的问题。所有这些都在毫秒范围内。调查实际的执行计划。您还可以使用 SQL Profiler 来跟踪正在执行的内容以及执行时间。等待和阻塞也可能是需要这么长时间的原因。