Войти

Показать полную графическую версию : Очень долгое выполнение хранимой процедуры. Sql Server 2008


LilLoco
30-01-2013, 09:03
Доброе утро, уважаемые.

Появилась проблема. Есть хранимая процедура, которая используется в работе с MapInfo(MapBasic).
Ее код выглядит следующим образом:


ALTER PROCEDURE mipGet2gWeekDifference
@starttime date,
@colNumber int
AS

BEGIN

IF OBJECT_ID('dbo.mi2gDATA','U') IS NOT NULL
DROP TABLE dbo.mi2gDATA

SELECT CellId = this_t.CellId, CellName = this_t.Cell_Name, Data = this_t.this - prev_t.prev,
PriValues = this_t.this, SlValues = prev_t.prev
INTO mi2gDATA
FROM
(SELECT data.starttime, info.CellId, info.Cell_Name,
this = CASE @colNumber
WHEN 1 THEN AVG(data.SDCCH_traffic_ave)
WHEN 2 THEN AVG(data.SDCCH_congest_time)
WHEN 3 THEN AVG(CAST(data.SDCCH_real_blocking AS Real) / 100)
WHEN 4 THEN AVG((100 - CAST(data.Total_HO_success As REAL) / 100))
WHEN 5 THEN AVG(CAST(data.Total_HO_success As REAL) / 100)
WHEN 6 THEN AVG(CAST(data.TCH_drop_call AS Real) / 100)
WHEN 7 THEN AVG(CAST(data.TCH_call_block AS REAL) / 100)
WHEN 8 THEN AVG(data.Total_FTCH_seizure_time)
WHEN 9 THEN AVG(data.Total_HTCH_seizure_time)
WHEN 10 THEN AVG(CAST(data.CSSR_voice As Real) / 100)
WHEN 11 THEN AVG(data.TCH_traffic_sum)
WHEN 12 THEN AVG(data.UL_gprs_RLC)
WHEN 13 THEN AVG(data.DL_gprs_RLC)
WHEN 14 THEN AVG(data.UL_egprs_RLC)
WHEN 15 THEN AVG(data.DL_egprs_RLC)
WHEN 16 THEN AVG(CAST(data.Drop_Call_Cell As Real) / 100)
WHEN 17 THEN AVG(data.Drop_Call_Bss)
WHEN 18 THEN AVG(data.Drop_Call_Plmn)
END
FROM Data2GEvD data, t2gCells info
WHERE data.starttime = @starttime AND info.id = data.cell_Id
GROUP BY data.starttime, info.CellId, info.Cell_Name) this_t
LEFT JOIN
(SELECT data.starttime, info.CellId,
prev = CASE @colNumber
WHEN 1 THEN AVG(data.SDCCH_traffic_ave)
WHEN 2 THEN AVG(data.SDCCH_congest_time)
WHEN 3 THEN AVG(CAST(data.SDCCH_real_blocking AS Real) / 100)
WHEN 4 THEN AVG((100 - CAST(data.Total_HO_success As REAL) / 100))
WHEN 5 THEN AVG(CAST(data.Total_HO_success As REAL) / 100)
WHEN 6 THEN AVG(CAST(data.TCH_drop_call AS Real) / 100)
WHEN 7 THEN AVG(CAST(data.TCH_call_block AS REAL) / 100)
WHEN 8 THEN AVG(data.Total_FTCH_seizure_time)
WHEN 9 THEN AVG(data.Total_HTCH_seizure_time)
WHEN 10 THEN AVG(CAST(data.CSSR_voice As Real) / 100)
WHEN 11 THEN AVG(data.TCH_traffic_sum)
WHEN 12 THEN AVG(data.UL_gprs_RLC)
WHEN 13 THEN AVG(data.DL_gprs_RLC)
WHEN 14 THEN AVG(data.UL_egprs_RLC)
WHEN 15 THEN AVG(data.DL_egprs_RLC)
WHEN 16 THEN AVG(CAST(data.Drop_Call_Cell As Real) / 100)
WHEN 17 THEN AVG(data.Drop_Call_Bss)
WHEN 18 THEN AVG(data.Drop_Call_Plmn)
END
FROM Data2GEvD data, t2gCells info
WHERE data.starttime = DATEADD(day,-7,@starttime) AND info.id = data.cell_Id
GROUP BY data.starttime, info.CellId) prev_t
ON prev_t.CellId = this_t.CellId
END


Структура таблицы откуда берутся данные:



CREATE TABLE dbo.Data2GEvD
(
id INT IDENTITY NOT NULL,
cell_Id INT NOT NULL,
starttime DATE NOT NULL,
SDCCH_traffic_ave REAL,
SDCCH_congest_time REAL,
SDCCH_real_blocking SMALLINT,
Total_HO_success SMALLINT,
TCH_drop_call SMALLINT,
TCH_call_block SMALLINT,
Total_FTCH_seizure_time REAL,
Total_HTCH_seizure_time REAL,
CSSR_voice SMALLINT,
TCH_traffic_sum REAL,
UL_gprs_RLC REAL,
DL_gprs_RLC REAL,
UL_egprs_RLC REAL,
DL_egprs_RLC REAL,
Drop_Call_Cell SMALLINT,
Drop_Call_Bss REAL,
Drop_Call_Plmn REAL,
CONSTRAINT PK_Data2GEvD PRIMARY KEY (id)
)
GO

CREATE INDEX idateevd
ON dbo.Data2GEvD (starttime)
GO



В таблице записей, на данный момент, порядка 2 миллионов. Представленная выше процедура выполняется около 15 минут. И это очень очень много. При выполнении обычного запроса:


DECLARE @starttime date
DECLARE @colNumber int

SET @starttime = '2013-01-28'
SET @colNumber = 16

IF OBJECT_ID('dbo.mi2gDATA','U') IS NOT NULL
DROP TABLE dbo.mi2gDATA

SELECT CellId = this_t.CellId, CellName = this_t.Cell_Name, Data = this_t.this - prev_t.prev,
PriValues = this_t.this, SlValues = prev_t.prev
INTO mi2gDATA
FROM
(SELECT data.starttime, info.CellId, info.Cell_Name,
this = CASE @colNumber
WHEN 1 THEN AVG(data.SDCCH_traffic_ave)
WHEN 2 THEN AVG(data.SDCCH_congest_time)
WHEN 3 THEN AVG(CAST(data.SDCCH_real_blocking AS Real) / 100)
WHEN 4 THEN AVG((100 - CAST(data.Total_HO_success As REAL) / 100))
WHEN 5 THEN AVG(CAST(data.Total_HO_success As REAL) / 100)
WHEN 6 THEN AVG(CAST(data.TCH_drop_call AS Real) / 100)
WHEN 7 THEN AVG(CAST(data.TCH_call_block AS REAL) / 100)
WHEN 8 THEN AVG(data.Total_FTCH_seizure_time)
WHEN 9 THEN AVG(data.Total_HTCH_seizure_time)
WHEN 10 THEN AVG(CAST(data.CSSR_voice As Real) / 100)
WHEN 11 THEN AVG(data.TCH_traffic_sum)
WHEN 12 THEN AVG(data.UL_gprs_RLC)
WHEN 13 THEN AVG(data.DL_gprs_RLC)
WHEN 14 THEN AVG(data.UL_egprs_RLC)
WHEN 15 THEN AVG(data.DL_egprs_RLC)
WHEN 16 THEN AVG(CAST(data.Drop_Call_Cell As Real) / 100)
WHEN 17 THEN AVG(data.Drop_Call_Bss)
WHEN 18 THEN AVG(data.Drop_Call_Plmn)
END
FROM Data2GEvD data, t2gCells info
WHERE data.starttime = @starttime AND info.id = data.cell_Id
GROUP BY data.starttime, info.CellId, info.Cell_Name) this_t
LEFT JOIN
(SELECT data.starttime, info.CellId,
prev = CASE @colNumber
WHEN 1 THEN AVG(data.SDCCH_traffic_ave)
WHEN 2 THEN AVG(data.SDCCH_congest_time)
WHEN 3 THEN AVG(CAST(data.SDCCH_real_blocking AS Real) / 100)
WHEN 4 THEN AVG((100 - CAST(data.Total_HO_success As REAL) / 100))
WHEN 5 THEN AVG(CAST(data.Total_HO_success As REAL) / 100)
WHEN 6 THEN AVG(CAST(data.TCH_drop_call AS Real) / 100)
WHEN 7 THEN AVG(CAST(data.TCH_call_block AS REAL) / 100)
WHEN 8 THEN AVG(data.Total_FTCH_seizure_time)
WHEN 9 THEN AVG(data.Total_HTCH_seizure_time)
WHEN 10 THEN AVG(CAST(data.CSSR_voice As Real) / 100)
WHEN 11 THEN AVG(data.TCH_traffic_sum)
WHEN 12 THEN AVG(data.UL_gprs_RLC)
WHEN 13 THEN AVG(data.DL_gprs_RLC)
WHEN 14 THEN AVG(data.UL_egprs_RLC)
WHEN 15 THEN AVG(data.DL_egprs_RLC)
WHEN 16 THEN AVG(CAST(data.Drop_Call_Cell As Real) / 100)
WHEN 17 THEN AVG(data.Drop_Call_Bss)
WHEN 18 THEN AVG(data.Drop_Call_Plmn)
END
FROM Data2GEvD data, t2gCells info
WHERE data.starttime = DATEADD(day,-7,@starttime) AND info.id = data.cell_Id
GROUP BY data.starttime, info.CellId) prev_t
ON prev_t.CellId = this_t.CellId


выборка и вставка происходят моментально практически (максимум 2 секунды).
Как побороть эту проблему?
Спасибо.

Delirium
30-01-2013, 15:27
Хм. То есть тот же самый запрос, только с объявлением переменных, выполняется мгновенно, а через вызов процедуры тормозит?
А если вызвать процедуру из Management Studio примерно так:
SET @starttime = '2013-01-28'
SET @colNumber = 16
mipGet2gWeekDifference @starttime, @colNumber
Результат будет мгновенным или долгим? Если мгновенным, то процедура тут не при чем, проблема на клиенте. Если же долгим, то это будет мистикой. В этом случае запускаем монитор активности или сразу Profiler и начинаем мониторить запросы и смотреть время выполнения. Находим запрос нашей процедуры, пихаем ее код в новый запрос и просматриваем план выполнения. Как то так.

LilLoco
30-01-2013, 16:59
а через вызов процедуры тормозит? »
Да именно, так.
Если же долгим, то это будет мистикой »
Для меня это уже мистика)

вызвать процедуру из Management Studio примерно так »
Это, к сожалению, проверить сегодня нет возможности уже.
Причина в этом "мистическая". В таблицу каждый день добавляются данные. Вчера туда было добавлено, с задержкой, около 150 тысяч записей. Сегодня, в поисках проблемы, полез в проектирование таблицы, пересохранил. И опа, процедура быстро выполняется. В дальнейшем, залил еще отчет (порядка 20к записей) в таблицу. И снова обработка очень долгая. После чего снова полез в проектирование таблицы, и все встало на свои места.
Пока что отчетов новых не появилось, проверить не могу. Но завтра обязательно.

монитор активности или сразу Profiler »
Их необходимо запускать со стороны сервера? К сожалению, никогда не пользовался данными средствами(

P.S. К серверу, отсутствует физический доступ.

BlackEric
30-01-2013, 17:27
1. Сравните план запросов в обоих случаях.
2. Если после пересохранения начинает работать быстро, то возможно проблема со статистикой индексов.
После массовой вставки данных их лучше перестраивать.

3. Если вы запрос всегда выполняете после процедуры, то он может быстро выполняться только потому, что данные уже в кеше.

LilLoco
31-01-2013, 15:26
2. Если после пересохранения начинает работать быстро, то возможно проблема со статистикой индексов.
После массовой вставки данных их лучше перестраивать. »

А можно поподробнее, пожалуйста?

LilLoco
05-02-2013, 13:53
Результат будет мгновенным или долгим? »
Если запускать через Management Studio выполнение длится также очень долго.

их лучше перестраивать »
Постоянное перестроение индексов сильно нагружает подсистему ввода/вывода и процессора сервера SQL Server, переполняет журнал транзакций и может блокировать другие процессы.

Источник (http://technet.microsoft.com/ru-ru/magazine/gg703775.aspx)

Delirium
06-02-2013, 14:45
Их необходимо запускать со стороны сервера? »
Из оснастки MS SQL Management Studio.
1. Сравните план запросов в обоих случаях. »
Вот это надо сделать обязательно и будет виден результат.

LilLoco
06-02-2013, 15:37
Вот это надо сделать обязательно и будет виден результат. »
А вы не могли бы поподробнее. Я так "серьезно" еще не работал с Sql Server.
Что хотя бы нужно искать?




© OSzone.net 2001-2012