got*_*tqn 7 varchar sql-server-2012 update
我发现您可以使用子句(示例here和here)high performance updates对varchar(max),nvarchar(max),varbinary(max)列进行操作。不幸的是,官方文档中没有提到性能优化。.WRITE
谁能告诉有任何优化吗?有人做过性能测试吗?此外,如果有优化,我想它也只会影响特定情况。
该WRITE方法是最少记录的。如果您使用常规UPDATE语句,则会导致使用 覆盖整个字符串FULL LOGGING。当处理大量更新时,这会变得低效。
为了支持大值数据类型的更新,UPDATE语法支持.WRITE方法。由于其最小日志记录的性质(包括插入或附加新数据),这将导致较少的事务日志。
注意:如果目标是,则UPDATE使用方法将会失败。WRITELOBNULL
REGULAR UPDATE下面是一个快速而肮脏的重现,显示了使用和UPDATE使用方法生成的事务日志.WRITE。
--- create table
create table dbo.testWRITEUpdate (
ID int identity(1, 1)
,COMMENTS varchar(MAX) not null
)
go
insert into dbo.testWRITEUpdate (COMMENTS)
values (REPLICATE(CAST('KIN' as varchar(max)), 9000))
checkpoint
go
Run Code Online (Sandbox Code Playgroud)
---定期更新:
set statistics io on
begin tran
update dbo.testWRITEUpdate
set COMMENTS = STUFF(COMMENTS, 9, 55, '$$$$$(((())))))))))))))____GarbageData____ Entered ____')
where ID =1
set statistics io off
go
commit tran
Run Code Online (Sandbox Code Playgroud)
-- 统计IO输出
Table 'testWRITEUpdate'. Scan count 1, logical reads 1, physical reads 0, read-ahead reads 0, lob logical reads 15, lob physical reads 0, lob read-ahead reads 6.
Run Code Online (Sandbox Code Playgroud)
-- 生成事务日志 --> 6 条日志记录,54580 字节:

更新使用WRITE方法:
begin tran
set statistics io on
update dbo.testWRITEUpdate
set COMMENTS.WRITE('$$$$$(((())))))))))))))____GarbageData____ Entered ____',9,55)
where ID =1
set statistics io off
commit tran
go
Run Code Online (Sandbox Code Playgroud)
-- 统计IO
Table 'testWRITEUpdate'. Scan count 1, logical reads 1, physical reads 0, read-ahead reads 0, lob logical reads 1, lob physical reads 0, lob read-ahead reads 0.
Run Code Online (Sandbox Code Playgroud)
-- 生成事务日志 --> 3 条 464 字节的日志记录:

上述测试证明该WRITE方法在生成事务日志方面提供了更多好处,因为它是最小日志操作+产生较少的逻辑读取。
注意:这只是表面现象,可以进行更多测试来实际证明 WRITE 方法的性能是否比常规 UPDATE 更好,尤其是在处理 VARCHAR、NVARCHAR 或 VARBINARY 数据类型时。
更新(根据OP的要求):
下面是查找的查询sys.dm_tran_database_transactions
SELECT [database_transaction_log_bytes_used] FROM sys.dm_tran_database_transactions
WHERE [database_id] = DB_ID ('test_kin');
GO
Run Code Online (Sandbox Code Playgroud)
---或更详细的版本:
SELECT DTST.[session_id],
DES.[login_name] AS [Login Name],
DB_NAME (DTDT.database_id) AS [Database],
DTDT.[database_transaction_begin_time] AS [Begin Time],
-- DATEDIFF(ms,DTDT.[database_transaction_begin_time], GETDATE()) AS [Duration ms],
CASE DTAT.transaction_type
WHEN 1 THEN 'Read/write'
WHEN 2 THEN 'Read-only'
WHEN 3 THEN 'System'
WHEN 4 THEN 'Distributed'
END AS [Transaction Type],
CASE DTAT.transaction_state
WHEN 0 THEN 'Not fully initialized'
WHEN 1 THEN 'Initialized, not started'
WHEN 2 THEN 'Active'
WHEN 3 THEN 'Ended'
WHEN 4 THEN 'Commit initiated'
WHEN 5 THEN 'Prepared, awaiting resolution'
WHEN 6 THEN 'Committed'
WHEN 7 THEN 'Rolling back'
WHEN 8 THEN 'Rolled back'
END AS [Transaction State],
DTDT.[database_transaction_log_record_count] AS [Log Records],
DTDT.[database_transaction_log_bytes_used] AS [Log Bytes Used],
DTDT.[database_transaction_log_bytes_reserved] AS [Log Bytes RSVPd],
DEST.[text] AS [Last Transaction Text],
DEQP.[query_plan] AS [Last Query Plan]
FROM sys.dm_tran_database_transactions DTDT
INNER JOIN sys.dm_tran_session_transactions DTST
ON DTST.[transaction_id] = DTDT.[transaction_id]
INNER JOIN sys.[dm_tran_active_transactions] DTAT
ON DTST.[transaction_id] = DTAT.[transaction_id]
INNER JOIN sys.[dm_exec_sessions] DES
ON DES.[session_id] = DTST.[session_id]
INNER JOIN sys.dm_exec_connections DEC
ON DEC.[session_id] = DTST.[session_id]
LEFT JOIN sys.dm_exec_requests DER
ON DER.[session_id] = DTST.[session_id]
CROSS APPLY sys.dm_exec_sql_text (DEC.[most_recent_sql_handle]) AS DEST
OUTER APPLY sys.dm_exec_query_plan (DER.[plan_handle]) AS DEQP
ORDER BY DTDT.[database_transaction_log_bytes_used] DESC;
-- ORDER BY [Duration ms] DESC;
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1351 次 |
| 最近记录: |