Как узнать, почему статус spid приостановлен?Какие ресурсы ожидает spid?
-
21-12-2019 - |
Вопрос
Я бегу EXEC sp_who2 78
и я получаю следующее Результаты:
Как я могу узнать, почему его статус приостановлен?
Этот процесс является тяжелым INSERT
основано на дорогостоящем запросе.Большой SELECT
это позволяет получить данные из нескольких таблиц и записать около 3-4 миллионов строк в другую таблицу.
Здесь нет блокировок / блокировок.
Тот Самый waittype
это связано с is CXPACKET
.что я могу понять, потому что есть 9 78-х, как вы можете видеть на картинке ниже.
Что меня беспокоит и что я действительно хотел бы знать, так это почему номер 1 в SPID
78 приостановлен.
Я понимаю, что когда статус SPID
приостановлено - это означает, что процесс ожидает получения ресурса и возобновится, когда получит свой ресурс.
Как я могу найти более подробную информацию об этом?какой ресурс?почему он недоступен?
Я часто использую приведенный ниже код и его вариации, но есть ли что-нибудь еще, что я могу сделать, чтобы выяснить, почему SPID
приостановлено?
select *
from sys.dm_exec_requests r
join sys.dm_os_tasks t on r.session_id = t.session_id
where r.session_id = 78
Я уже использовал sp_whoisactive - активный.Результат, который я получаю для этого конкретного spid78, выглядит следующим образом:(разбито на 3 фотографии по размеру экрана)
Решение
ПРИОСТАНОВЛЕНО:Это означает, что запрос в данный момент не активен, поскольку он ожидает получения ресурса.Ресурс может быть средством ввода-вывода для чтения страницы, ожиданием - это может быть обмен данными в сети, или он ожидает блокировки или защелкивания.Он станет активным, как только задача, которой он ожидает, будет завершена.Например, если запрос the отправил запрос ввода-вывода на чтение данных полной таблицы tblStudents, то эта задача будет приостановлена до завершения ввода-вывода.Как только ввод-вывод будет завершен (данные для таблицы tblStudents доступны в памяти), запрос переместится в очередь выполнения.
Поэтому, если он ожидает, проверьте столбец wait_type, чтобы понять, чего он ожидает, и устранить неполадки на основе wait_time.
Я разработал следующую процедуру, которая помогает мне в этом, она включает в себя WAIT_TYPE.
use master
go
CREATE PROCEDURE [dbo].[sp_radhe]
AS
BEGIN
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED
SELECT es.session_id AS session_id
,COALESCE(es.original_login_name, '') AS login_name
,COALESCE(es.host_name,'') AS hostname
,COALESCE(es.last_request_end_time,es.last_request_start_time) AS last_batch
,es.status
,COALESCE(er.blocking_session_id,0) AS blocked_by
,COALESCE(er.wait_type,'MISCELLANEOUS') AS waittype
,COALESCE(er.wait_time,0) AS waittime
,COALESCE(er.last_wait_type,'MISCELLANEOUS') AS lastwaittype
,COALESCE(er.wait_resource,'') AS waitresource
,coalesce(db_name(er.database_id),'No Info') as dbid
,COALESCE(er.command,'AWAITING COMMAND') AS cmd
,sql_text=st.text
,transaction_isolation =
CASE es.transaction_isolation_level
WHEN 0 THEN 'Unspecified'
WHEN 1 THEN 'Read Uncommitted'
WHEN 2 THEN 'Read Committed'
WHEN 3 THEN 'Repeatable'
WHEN 4 THEN 'Serializable'
WHEN 5 THEN 'Snapshot'
END
,COALESCE(es.cpu_time,0)
+ COALESCE(er.cpu_time,0) AS cpu
,COALESCE(es.reads,0)
+ COALESCE(es.writes,0)
+ COALESCE(er.reads,0)
+ COALESCE(er.writes,0) AS physical_io
,COALESCE(er.open_transaction_count,-1) AS open_tran
,COALESCE(es.program_name,'') AS program_name
,es.login_time
FROM sys.dm_exec_sessions es
LEFT OUTER JOIN sys.dm_exec_connections ec ON es.session_id = ec.session_id
LEFT OUTER JOIN sys.dm_exec_requests er ON es.session_id = er.session_id
LEFT OUTER JOIN sys.server_principals sp ON es.security_id = sp.sid
LEFT OUTER JOIN sys.dm_os_tasks ota ON es.session_id = ota.session_id
LEFT OUTER JOIN sys.dm_os_threads oth ON ota.worker_address = oth.worker_address
CROSS APPLY sys.dm_exec_sql_text(er.sql_handle) AS st
where es.is_user_process = 1
and es.session_id <> @@spid
ORDER BY es.session_id
end
Приведенный ниже запрос также может показать основную информацию, которая поможет при приостановке spid, показывая, какой ресурс ожидает spid.
SELECT wt.session_id,
ot.task_state,
wt.wait_type,
wt.wait_duration_ms,
wt.blocking_session_id,
wt.resource_description,
es.[host_name],
es.[program_name]
FROM sys.dm_os_waiting_tasks wt
INNER JOIN sys.dm_os_tasks ot ON ot.task_address = wt.waiting_task_address
INNER JOIN sys.dm_exec_sessions es ON es.session_id = wt.session_id
WHERE es.is_user_process = 1
Пожалуйста, посмотрите на картинку ниже в качестве примера:
Другие советы
Я использую sp_whoisctive, чтобы посмотреть эту информацию, поскольку это готовый бесплатный инструмент, который дает вам хорошую информацию для устранения неисправностей медленных запросов:
С этим вы можете получить текст запроса, план его использует, ресурс запроса ждет, что он блокирует его, какие блокировки он вынимает и многое другое.
намного проще, чем пытаться катиться своим собственным.
Вы можете решить это с путями:
- исправить индекс кластера.
- Используйте временные таблицы, чтобы получить часть всей таблицы и работать с ней.
У меня такая же проблема со столом с 400 000 000 строк, и используйте временные таблицы, чтобы получить часть этого, а затем я использую свои фильтры и усталы, потому что изменение индекса не было вариантом.
Некоторые примеры:
--
--this is need be cause DECLARE @TEMPORAL are not well for a lot of data.
CREATE TABLE #TEMPORAL
(
ID BIGINT,
ID2 BIGINT,
DATA1 DECIMAL,
DATA2 DECIMAL
);
WITH TABLE1 AS
(
SELECT
L.ID,
L.ID2,
L.DATA
FROM LARGEDATA L
WHERE L.ID = 1
), WITH TABLE2 AS
(
SELECT
L.ID,
L.ID2,
L.DATA
FROM LARGEDATA L
WHERE L.ID = 2
) INSERT INTO #TEMPORAL SELECT
T1.ID,
T2.ID,
T1.DATA,
T2.DATA
FROM TABLE1 T1
INNER JOIN TABLE2 T2
ON T2.ID2 = T2.ID2;
--
--this take a lot of resources proces and time and be come a status suspend, this why i need a temporal table.
SELECT
*
FROM #TEMPORAL T
WHERE T.DATA1 < T.DATA2
--
--IMPORTANT DROP THE TABLE.
DROP TABLE #TEMPORAL
.