我有一个拥有三千万行的数据库。主键聚集索引是由代码生成的GUID
。
表格如下:
CREATE TABLE [dbo].[events](
[imageEventGUID] [uniqueidentifier] NOT NULL,
[imageSHAID] [nvarchar](256) NOT NULL,
[queryGUID] [uniqueidentifier] NOT NULL,
[eventType] [int] NOT NULL,
[eventValue] [nvarchar](2050) NULL,
[dateOfEvent] [datetime] NOT NULL,
CONSTRAINT [PK_store_image_event] PRIMARY KEY CLUSTERED
(
[imageEventGUID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
简单来说,这是一个图像搜索引擎。
imageEventGUID
是唯一标识符代码,imageSHAID
是图像 URL 的 SHA256 值queryGUID
是生成的外键代码(为简洁起见,在创建语句中排除)eventType
是分配给事件类型的数字eventValue
通常是图像的 URI,例如 "http://mywebpage.com/images/image123456789.jpg"
SqlBulkCopy
(从 DataTable
)将数据插入此表中:using (SqlBulkCopy bulk = new SqlBulkCopy(storeConn, SqlBulkCopyOptions.KeepIdentity | SqlBulkCopyOptions.KeepNulls, null))
{
bulk.DestinationTableName = "[dbo].[events]";
bulk.WriteToServer(myeventsDataTable);
}
我通常试图一次性批量插入5k到10k行数据。但是,从这个大容量复制中,我的插入效果很差。我曾经在SSD上运行此数据库(只连接SATA 1),非常快速(低于500毫秒)。由于SSD空间不足,所以我将DB换成了1TB 7200缓存旋转磁盘,自那时起,完成时间超过了120秒(120000毫秒)。当批量插入正在运行时,我可以看到大约1MB/秒的磁盘活动量,CPU使用率较低。
除PK外,此表上没有其他索引。
以下是我的问题:
您是否能看出我做错了什么导致这种情况?
只是因为“您的旋转磁盘不够快,无法满足这个DB的大小”吗?
在插入此数据时,确切发生了什么?因为它是聚集索引,所以在进行插入时,它是否重新排列磁盘上的数据页?它正试图插入GUIDS,因其本质上是无序的,因此可能会导致“随机插入性质”的读/写头在磁盘上移动到不同的页面?
感谢您的时间。
SqlBulkCopyOptions.KeepIdentity
,但是你没有一个自增列,为什么?另外,是否有其他东西与同一张表进行通信(读或写)?这可能会导致锁争用。 - Scott ChamberlainGUID
作为聚集主键本身就是一个非常糟糕的设计选择。请参考Kim Tripp的博客文章GUIDs as PRIMARY KEYs and/or the clustering key了解详细说明。 - marc_s