簡體   English   中英

SQL Server:MERGE性能

[英]SQL Server : MERGE performance

我有一個包含500萬行的數據庫表。 聚簇索引是自動增量標識列。 PK是一個生成256字節VARCHAR的代碼,它是一個URL的SHA256哈希,這是表上的非聚集索引。

表格如下:

CREATE TABLE [dbo].[store_image](
    [imageSHAID] [nvarchar](256) NOT NULL,
    [imageGUID] [uniqueidentifier] NOT NULL,
    [imageURL] [nvarchar](2000) NOT NULL,
    [showCount] [bigint] NOT NULL,
    [imageURLIndex]  AS (CONVERT([nvarchar](450),[imageURL],(0))),
    [autoIncID] [bigint] IDENTITY(1,1) NOT NULL,
 CONSTRAINT [PK_imageSHAID] PRIMARY KEY NONCLUSTERED 
(
    [imageSHAID] 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

CREATE CLUSTERED INDEX [autoIncPK] ON [dbo].[store_image] 
(
    [autoIncID] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
GO
  • imageSHAID是圖像URL的SHA256哈希,例如“ http://blah.com/image1.jpg ”,它被散列為256個長度的varchar。

  • imageGUID是一個代碼生成的guid,我在其中識別圖像(稍后將用作索引,但是現在我已將此列省略為索引)

  • imageURLimageURL的完整URL(最多2000個字符)

  • showCount是圖像顯示的次數,每次顯示此特定圖像時都會遞增。

  • imageURLIndex是一個受450個字符限制的計算列,這允許我在imageURL上進行文本搜索,如果我選擇,它是可索引的(為了簡潔,省略了index)

  • autoIncID是聚簇索引,應該允許更快地插入數據。

我定期將臨時表合並到store_image表中。 臨時表結構如下(非常類似於store_image表):

CREATE TABLE [dbo].[store_image_temp](
    [imageSHAID] [nvarchar](256) NULL,
    [imageURL] [nvarchar](2000) NULL,
    [showCount] [bigint] NULL,
) ON [PRIMARY]

GO

運行合並過程時,我使用以下代碼將一個DataTable寫入臨時表:

using (SqlBulkCopy bulk = new SqlBulkCopy(storeConn, SqlBulkCopyOptions.KeepIdentity | SqlBulkCopyOptions.KeepNulls, null))
{
    bulk.DestinationTableName = "[dbo].[store_image_temp]";
    bulk.WriteToServer(imageTableUpsetDataTable);
}

我然后運行合並命令來更新showCountstore_image通過基於該臨時表合並表imageSHAID 如果store_image表中當前不存在圖像,我創建它:

merge into store_image as Target using [dbo].[store_image_temp] as Source
on Target.imageSHAID=Source.imageSHAID 
when matched then update set 
Target.showCount=Target.showCount+Source.showCount 
when not matched then insert values (Source.imageSHAID,NEWID(), Source.imageURL, Source.showCount);

我通常嘗試在任何一個合並過程中將臨時表中的2k-5k行合並到store_image表。

我以前在SSD(僅連接SATA 1)上運行此DB,速度非常快(200 ms以下)。 我在SSD上跑出了房間,所以我將數據庫換成1TB 7200緩存旋轉磁盤,因為完成時間超過6-100秒(6000 - 100000MS)。 當批量插件運行時,我可以看到大約1MB-2MB /秒的磁盤活動,CPU使用率低。

這是這個數據量的典型寫入時間嗎? 對我來說似乎有點慢,導致性能下降的原因是什么? 當然imageSHAID被編入索引,我們應該期待更快的搜索時間嗎?

任何幫助,將不勝感激。

謝謝你的時間。

MERGE UPDATE子句更新showCount 這需要在聚簇索引上進行密鑰查找。

但是,聚簇索引也聲明為非唯一。 即使基礎列是唯一的,這也會為優化器提供信息。

所以,我會做出這些改變

  • 群集主鍵是autoIncID
  • imageSHAID上的當前PK是獨立的唯一索引(不是約束),並為showCount添加INCLUDE。 唯一約束不能包含INCLUDE

更多觀察:

  • 您不需要nvarchar作為哈希或URL列。 這些不是unicode。
  • 散列也是固定長度,因此可以是char(64) (對於SHA2-512)。
  • 列的長度定義要分配給查詢的內存量。 有關更多內容,請參閱此內容: varchar(500)優於varchar(8000)是否有優勢?

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM