当 nvarchar(max) 列具有几 MB 数据时,我在表上的单行插入/更新语句上遇到性能不佳的问题。
这是我的表结构:
CREATE TABLE [dbo].[tbl_set_Cart](
[ID] [int] NOT NULL,
[AS400_CUSTOMER_COD] [nvarchar](50) NOT NULL,
[AS400_LISTIN] [int] NOT NULL,
[VALUE] [nvarchar](max) NOT NULL,
[DELIVERY_COSTS] [nvarchar](max) NOT NULL,
[ITEMS_COUNT] [int] NOT NULL,
[ITEMS] [nvarchar](max) NOT NULL,
[KIND] [int] NOT NULL,
[CHECKOUT_INFO] [nvarchar](max) NOT NULL,
[ISSUES] [nvarchar](max) NOT NULL,
[LAST_CHECK] [datetime] NOT NULL,
[USER_ID] [int] NOT NULL,
[IMPERSONATED_USER_ID] [int] NOT NULL,
[OVERRIDE_PRICES] [bit] NOT NULL,
[HAS_ISSUE] [bit] NOT NULL,
[IS_CONFIRMED] [bit] NOT NULL,
[IS_COLLECTED] [bit] NOT NULL,
[_METADATA] [nvarchar](max) NOT NULL,
CONSTRAINT [PK_tbl_set_Cart] PRIMARY KEY CLUSTERED
(
[ID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO
这里是一个更新语句的例子
DECLARE @p0 AS INT = [cart_id];
DECLARE @p1 AS INT = [entry_count];
DECLARE @p2 AS NVARCHAR(MAX) = '..document..' --~8MB;
UPDATE [dbo].[tbl_set_Cart]
SET [ITEMS_COUNT] = @p1, [ITEMS] = @p2
WHERE [ID] = @p0
在数据库的同一台机器上执行这个命令(一个开发环境,所以没有其他工作负载)我得到了这个性能:
将文本加载到 SQL Server 中这么慢真的让我感到惊讶,所以我要问的是是否有更好的方法来实现这一点。
该文档是一个大的 JSON,不会超过 10MB 的数据(我已经在最坏的情况下完成了上面报告的基准测试),如果性能提高,我将其转换为 BLOB 或其他数据结构没有问题。如果这是一个更好的主意,我还可以使用存储过程来上传大文本。
环境:
Windows Server 2019 16 逻辑处理器 2,1 GHz 和 Microsoft SQL Server Standard(64 位)版本 15.0.2070.41,具有 4GB 预留 RAM,16 核许可。
(这是一个仅限开发的环境,在这种情况下,我是唯一一个没有其他程序或计划活动运行的人。)
我在这里再次测试了一个不同的购物车(一个小一点的)(客户统计数据)和执行计划。
链接在这里:https ://www.brentozar.com/pastetheplan/?id=SJcPhDUFK
如果我插入一个新行,它会更快:
链接在这里:https ://www.brentozar.com/pastetheplan/?id=S1FDjD8KF
对于插入语句,我使用了 SQL Server 生成的数据(任务 -> 脚本表 -> 仅限数据)
我期望实现的是更新时间 <0,5s
在我的场景中,json 通常出生时很小,然后每天都在增加,直到我正在测试的大小。我可以开始考虑将它们存储为文件吗?
我在日志文件中预先分配了空间。并再次检查恢复模式是否设置为简单。我可以做些什么来进一步提高性能?
您的缓慢更新计划显示要等待很长时间
LOGBUFFER
:您应该检查数据库的日志文件是否位于足够快的存储空间以应对工作负载。
增加实例可用的 RAM 量也可能带来一些好处。
PAGEIOLATCH_EX
等待时间也很长,为 361 毫秒。正如大卫布朗建议的那样,您还可以:
COMPRESS
JSON 将一些 IO 转移到 CPU。PAGEIOLATCH
等待。我建议您尝试将 json 信息放入/复制到“本地”目录(在数据库服务器上或附近)的文件中,然后使用该
OPENROWSET BULK
功能请参阅 https://techcommunity.microsoft.com/t5/sql-server-blog/importing-json-files-into-sql-server-using-openrowset-bulk/ba-p/384480