SQL Server:合并性能

2023-12-06

我有一个包含 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,我在其中标识图像(稍后将用作索引,但现在我省略了此列作为索引)

  • imageURL是图像的完整 URL(最多 2000 个字符)

  • showCount是图像显示的次数,每次显示该特定图像时都会递增。

  • imageURLIndex是一个限制为 450 个字符的计算列,这允许我在 imageURL 上进行文本搜索(如果我选择的话),它是可索引的(为了简洁起见,再次省略了索引)

  • 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);
}

然后我运行合并命令来更新showCount in the store_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),速度非常快(低于 200 毫秒)。我的 SSD 空间不足,因此我将 DB 更换为 1TB 7200 缓存旋转磁盘,此后完成时间超过 6-100 秒(6000 - 100000MS)。当批量插入运行时,我可以看到磁盘活动约为 1MB-2MB/秒,CPU 使用率较低。

这是这种数据量的典型写入时间吗?我觉得有点慢,是什么导致性能缓慢?肯定与imageSHAID被索引后,我们应该期望比这更快的寻道时间?

任何帮助,将不胜感激。

谢谢你的时间。


Your UPDATE中的条款MERGE更新showCount。这需要对聚集索引进行键查找。

然而,聚集索引也被声明为非唯一的。即使基础列是唯一的,这也会向优化器提供信息。

所以,我会做出这些改变

  • 聚集主键为autoIncID
  • 目前的PKimageSHAID成为独立的唯一索引(非约束)并添加 INCLUDEshowCount。唯一约束不能包含 INCLUDE

更多观察:

  • 你不需要nvarchar对于哈希或 URL 列。这些不是 unicode。
  • 哈希值也是固定长度的,因此可以char(64)(对于 SHA2-512)。
  • 列的长度定义分配给查询的内存量。请参阅此了解更多信息:varchar(500) 比 varchar(8000) 有优势吗?
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

SQL Server:合并性能 的相关文章

  • 如何在 SqlDataReader.Read() 期间从死锁异常中恢复

    我的 NET 应用程序的事件日志显示 它在从 Sql Server 读取数据时偶尔会出现死锁 这种情况通常非常罕见 因为我们已经优化了查询以避免死锁 但有时仍然会发生 过去 我们在调用ExecuteReader函数在我们的SqlComman
  • 如何在事务中使用链接服务器插入远程表?

    我的链接服务器设置正确 我能够执行以下查询 插入 远程服务器 表 SELECT FROM 本地服务器 表 然而当我做同样的事情时交易内 开始传输 插入 远程服务器 表 SELECT FROM 本地服务器 表 提交交易 我收到类似的错误 用于
  • SQL Server 中的嵌套事务

    sql server 允许嵌套事务吗 如果是的话那么交易的优先级是什么 来自 SQL Server 上的 MSDN 文档 嵌套交易 http msdn microsoft com en us library ms189336 SQL 90
  • 计算包含字母/数字的行数

    我想要实现的目标很简单 但是解释起来有点困难 我不知道在 postgres 中这是否真的可能 我处于相当基础的水平 SELECT FROM WHERE LEFT JOIN ON HAVING 等等基本的东西 我正在尝试计算包含特定字母 数字
  • MySQL 最佳实践:SELECT 子递归尽可能提高性能?

    我想选择一个根项目及其子项 使其性能尽可能高 我更喜欢使用嵌套集模型 但这次表结构遵循邻接模型 有关嵌套集和邻接模型的更多信息 http mikehillyer com articles managing hierarchical data
  • 如何搜索表中的所有列?

    如何在 SQL Server 中搜索表的所有列 SELECT FROM yourtable WHERE val IN field1 field2 field3 field4 如果您正在寻找精确的全场比赛 如果你正在寻找子字符串匹配 你将不得
  • sql join 告诉我 ID 是否存在于其他表中

    我有 2 张桌子 A B ID FKID 1 3 2 3 3 4 4 4 我需要一个 select 语句 它显示 A 的所有内容 其中一个字段告诉我表 B 是否有任何与该 ID 匹配的 id Desired Result ID hasB 1
  • Sql Server 的夏令时

    我们正在使用一个以 C Unix 格式存储日期的旧应用程序 C 时间基本上是自 1970 年 1 月 1 日以来的秒数 日期以整数形式存储在 SQL Server 数据库中 我正在为使用这些日期的报告编写视图 到目前为止 我正在使用以下命令
  • Postgres LIMIT/OFFSET 奇怪的行为

    我正在使用 PostgreSQL 9 6 我有一个这样的查询 SELECT anon 1 id AS anon 1 id anon 1 is valid AS anon 1 is valid anon 1 first name AS ano
  • 在 SQL Server 中将 UTC 毫秒转换为 DATETIME

    我想在 SQL Server 中将 UTC 毫秒转换为 DateTime 这可以通过以下代码在 C 中轻松完成 DateTime startDate new DateTime 1970 1 1 AddMilliseconds 1348203
  • 使用转义换行符和回车符取消转义字符串

    我正在尝试编写一个 PLPGSQL 函数来混淆 审查 编辑文本 Obfuscate a body of text by replacing lowercase letters and numbers with symbols CREATE
  • 将图像列保存到 SQL Server 2000 中的文件

    我在 SQL Server 2000 中有一个包含图像列的表 我需要将图像数据保存到文件系统上的文件中 在 SQL Server 2005 中 我可以使用 ADODB Stream 对象进行文件 I O 但这在 SQL Server 200
  • Oracle 删除约束级联等效于 Sql Server

    在Oracle中 删除约束PK SAI我使用语法 ALTER TABLE SAISIE DROP CONSTRAINT PK SAI CASCADE SQL Server 中与此等效的是什么 您正在考虑与实际 DELETE 语句相关的 FO
  • 对于返回超过1个值的SQL select,当Id为GUID时它们如何排序?

    我想知道 SQL Server 如何对查询返回的数据进行排序 并且各个表的 Id 列都是 uniqueidentifier 类型 我在创建所有 GUID 时使用 NHibernate GuidComb 并执行以下操作 Sheet sheet
  • SQL Server Like 查询不区分大小写

    Query SELECT from Table 2 WHERE name like Joe Output 1 100 Joe 2 200 JOE 3 300 jOE 4 400 joe 为什么不区分大小写 Problem 查询不区分大小写
  • 删除重复的行并需要在mysql中保留所有行中的一个[重复]

    这个问题在这里已经有答案了 我想删除基于两列的重复行 但需要保留所有行 1 行 重复行可以多于两行 例如 ID NAME PHONE 1 NIL 1234 2 NIL 1234 3 NIL 1234 4 MES 5989 我想从上面 3 行
  • 如何将 sql 数据输出到 QCalendarWidget

    我希望能够在日历小部件上突出显示 SQL 数据库中的一天 就像启动程序时突出显示当前日期一样 在我的示例中 它是红色突出显示 我想要发生的是 当用户按下突出显示的日期时 数据库中日期旁边的文本将显示在日历下方的标签上 这是我使用 QT De
  • 创建日期范围表

    我正在编写一份需要显示每天值的报告 我有查询的开始日期和结束日期 但我希望避免丢失日期 以防表不包含特定日期的值 我正在考虑创建一个基本日期范围表 其中包含开始和结束之间的所有日期 然后将其与数据表左连接以显示每一天的值 我找到了一些适用于
  • 在 SQL 中按键组对行进行顺序编号?

    SQL中有没有办法按顺序添加行号按关键组 假设一个表包含任意 CODE NAME 元组 示例表 CODE NAME A Apple A Angel A Arizona B Bravo C Charlie C Cat D Dog D Dopp
  • Python 中的 Unix cat 函数 (cat * > merged.txt)? [复制]

    这个问题在这里已经有答案了 一旦建立了目录 有没有办法在Python中使用Unix中的cat函数或类似的函数 我想将 files 1 3 合并到 merged txt 我通常会在 Unix 中找到该目录 然后运行 cat gt merged

随机推荐