Компьютерный форум OSzone.net  

Компьютерный форум OSzone.net (http://forum.oszone.net/index.php)
-   Программирование и базы данных (http://forum.oszone.net/forumdisplay.php?f=21)
-   -   Очень долгое выполнение хранимой процедуры. Sql Server 2008 (http://forum.oszone.net/showthread.php?t=252684)

LilLoco 30-01-2013 09:03 2078280

Очень долгое выполнение хранимой процедуры. Sql Server 2008
 
Доброе утро, уважаемые.

Появилась проблема. Есть хранимая процедура, которая используется в работе с 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 2078570

Хм. То есть тот же самый запрос, только с объявлением переменных, выполняется мгновенно, а через вызов процедуры тормозит?
А если вызвать процедуру из Management Studio примерно так:
Код:

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

Результат будет мгновенным или долгим? Если мгновенным, то процедура тут не при чем, проблема на клиенте. Если же долгим, то это будет мистикой. В этом случае запускаем монитор активности или сразу Profiler и начинаем мониторить запросы и смотреть время выполнения. Находим запрос нашей процедуры, пихаем ее код в новый запрос и просматриваем план выполнения. Как то так.

LilLoco 30-01-2013 16:59 2078653

Цитата:

Цитата Delirium
а через вызов процедуры тормозит? »

Да именно, так.
Цитата:

Цитата Delirium
Если же долгим, то это будет мистикой »

Для меня это уже мистика)

Цитата:

Цитата Delirium
вызвать процедуру из Management Studio примерно так »

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

Цитата:

Цитата Delirium
монитор активности или сразу Profiler »

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

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

BlackEric 30-01-2013 17:27 2078672

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

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

LilLoco 31-01-2013 15:26 2079384

Цитата:

Цитата BlackEric
2. Если после пересохранения начинает работать быстро, то возможно проблема со статистикой индексов.
После массовой вставки данных их лучше перестраивать. »

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

LilLoco 05-02-2013 13:53 2082952

Цитата:

Цитата Delirium
Результат будет мгновенным или долгим? »

Если запускать через Management Studio выполнение длится также очень долго.

Цитата:

Цитата BlackEric
их лучше перестраивать »

Цитата:

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


Delirium 06-02-2013 14:45 2083694

Цитата:

Цитата LilLoco
Их необходимо запускать со стороны сервера? »

Из оснастки MS SQL Management Studio.
Цитата:

Цитата BlackEric
1. Сравните план запросов в обоих случаях. »

Вот это надо сделать обязательно и будет виден результат.

LilLoco 06-02-2013 15:37 2083742

Цитата:

Цитата Delirium
Вот это надо сделать обязательно и будет виден результат. »

А вы не могли бы поподробнее. Я так "серьезно" еще не работал с Sql Server.
Что хотя бы нужно искать?


Время: 23:02.

Время: 23:02.
© OSzone.net 2001-