Mar*_*cus 3 performance sql-server query-performance
我有一个大约有 1100 万行的表,定义为:
CREATE TABLE [sko].[stage_närvaro](
[datum_fakta] [datetime] NULL,
[person_id] nvarchar NULL,
[läsår_fakta] nvarchar NULL,
[termin_fakta] nvarchar NULL,
[period_fakta] nvarchar NULL,
[vecka_fakta] nvarchar NULL,
[veckodag_fakta] nvarchar NULL,
[ämne_id] nvarchar NULL,
[ämne] nvarchar NULL,
[frånvaro_min] [float] NULL,
[närvaro_min] [float] NULL,
[frånvaroorsak_id] nvarchar NULL,
[frånvaroorsak] nvarchar NULL,
[beskrivning] nvarchar NULL,
[personal_id] nvarchar NULL,
[försystem] nvarchar NULL
)
Run Code Online (Sandbox Code Playgroud)
使用以下非聚集索引:
CREATE NONCLUSTERED INDEX [stage_skola_närvaro_ix1] ON [sko].[stage_närvaro]
(
[person_id] ASC,
[termin_fakta] ASC,
[läsår_fakta] ASC
)
Run Code Online (Sandbox Code Playgroud)
当我运行以下删除查询时,至少需要 2 个多小时才能完成。
DELETE sko.stage_närvaro
FROM sko.stage_närvaro e
WHERE försystem = 'Extens'
AND EXISTS (
SELECT *
FROM ext.v_imp_närvaro v
WHERE e.person_id = v.person_id
AND e.termin_fakta = v.termin_fakta
AND e.läsår_fakta = v.läsår_fakta
)
Run Code Online (Sandbox Code Playgroud)
我的删除查询是否使用我的索引?在删除之前禁用索引是否有帮助,然后再启用它?
编辑:视图ext.v_imp_närvaro与表的行数相同sko.stage_närvaro。
EDIT2:我怀疑这是一个I / O问题,所以我跑下面的查询,通过DaniSQL建议在这里:
SELECT TOP 10
wait_type ,
max_wait_time_ms wait_time_ms ,
signal_wait_time_ms ,
wait_time_ms - signal_wait_time_ms AS resource_wait_time_ms ,
100.0 * wait_time_ms / SUM(wait_time_ms) OVER ( ) AS percent_total_waits ,
100.0 * signal_wait_time_ms / SUM(signal_wait_time_ms) OVER ( ) AS percent_total_signal_waits ,
100.0 * ( wait_time_ms - signal_wait_time_ms )
/ SUM(wait_time_ms) OVER ( ) AS percent_total_resource_waits
FROM sys.dm_os_wait_stats
WHERE wait_time_ms > 0 -- remove zero wait_time
AND wait_type NOT IN -- filter out additional irrelevant waits
( 'SLEEP_TASK', 'BROKER_TASK_STOP', 'BROKER_TO_FLUSH', 'SQLTRACE_BUFFER_FLUSH',
'CLR_AUTO_EVENT', 'CLR_MANUAL_EVENT', 'LAZYWRITER_SLEEP', 'SLEEP_SYSTEMTASK',
'SLEEP_BPOOL_FLUSH', 'BROKER_EVENTHANDLER', 'XE_DISPATCHER_WAIT',
'FT_IFTSHC_MUTEX', 'CHECKPOINT_QUEUE', 'FT_IFTS_SCHEDULER_IDLE_WAIT',
'BROKER_TRANSMITTER', 'FT_IFTSHC_MUTEX', 'KSOURCE_WAKEUP',
'LAZYWRITER_SLEEP', 'LOGMGR_QUEUE', 'ONDEMAND_TASK_QUEUE',
'REQUEST_FOR_DEADLOCK_SEARCH', 'XE_TIMER_EVENT', 'BAD_PAGE_PROCESS',
'DBMIRROR_EVENTS_QUEUE', 'BROKER_RECEIVE_WAITFOR',
'PREEMPTIVE_OS_GETPROCADDRESS', 'PREEMPTIVE_OS_AUTHENTICATIONOPS', 'WAITFOR',
'DISPATCHER_QUEUE_SEMAPHORE', 'XE_DISPATCHER_JOIN', 'RESOURCE_QUEUE' )
ORDER BY wait_time_ms DESC
Run Code Online (Sandbox Code Playgroud)
结果如下。我不确定如何解释它们。
我不完全了解您的环境,即所讨论的表是否主要用于写入或读取。
您多久执行一次删除操作?
[sko].[stage_närvaro] 的主键和聚集索引是什么?
如果我想优化此删除操作,我会考虑以下几点:
1) 视图 ext.v_imp_närvaro 的基础表上的索引,其中包含 select (person_id, termin_fakta,[läsår_fakta]) 中使用的列,您最有可能希望在那里寻找索引(不需要包含任何列,因为您只是要去那里是存在的)
2)我一直在使用很多过滤索引,我会考虑以下几点:
CREATE NONCLUSTERED INDEX IDXF_STAGE_NARVARO_FORSYSTEMS_EXTENS
ON [sko].[stage_närvaro] ([försystem])
INCLUDE ([person_id],[termin_fakta],[läsår_fakta])
WHERE [försystem] = 'Extens'
Run Code Online (Sandbox Code Playgroud)
3)我可以看到一些LCK_M_S在那里进行,不确定是否与此查询特别相关,但我尝试始终使用 ROWCOUNT 并批量进行大删除和更新,如下所示:
USE DATABASENAME
GO
DECLARE @RC INT
SELECT @RC = 0
SET ROWCOUNT 5000
WHILE (1 = 1)
BEGIN
BEGIN TRANSACTION
DELETE sko.stage_närvaro
FROM sko.stage_närvaro e
WHERE försystem = 'Extens'
AND EXISTS (
SELECT *
FROM ext.v_imp_närvaro v
WHERE e.person_id = v.person_id
AND e.termin_fakta = v.termin_fakta
AND e.läsår_fakta = v.läsår_fakta
)
SELECT @RC = @@ROWCOUNT
print CAST ( DB_NAME() AS VARCHAR(500) ) +
' -- ' + CAST ( @RC AS VARCHAR(10) ) + ' --> ' +
CAST( GETDATE() AS VARCHAR(25))
WAITFOR DELAY '00:00:01';
IF @RC = 0
BEGIN
COMMIT TRANSACTION
BREAK
END
COMMIT TRANSACTION
END
SET ROWCOUNT 0
--==============================================================
--SET ROWCOUNT 10000 -- define maximum updated rows at once
-- DO THE UPDATE
-- don't forget about bellow
-- after everything is updated
--SET ROWCOUNT 0
-- Setting ROWCOUNT to 0 turn off limits - don't forget about it.
--===============================================================
Run Code Online (Sandbox Code Playgroud)
这可能不是一个全面的解决方案,因为这个问题也有一些遗漏,但是,它肯定会给你一些想法,作为改进大删除操作的可能方法。