Sql Delete Query Optimization для Azure - PullRequest
       7

Sql Delete Query Optimization для Azure

0 голосов
/ 29 января 2019

Мне нужна помощь с оптимизацией следующего запроса.

Моя проблема

Я пытаюсь очистить таблицу на основе параметра size . (удалить x Мб из этой таблицы) .Я подумал, как реализовать его: перебрать таблицу, начиная с самой старой записи, получить каждый размер строки (я учитываю только столбцы BLOB-объектов), перебрать все связанные таблицы и выполнить для них ту же операцию;if currentSize >= size остановите запрос и верните список GUIDs найден

Обратите внимание, что это часть более крупного запроса, поэтому в конце мне нужен список идентификаторов.

То, что я пробовал

Сначала я попытался написать его, используя EntityFramework, но его выполнение заняло слишком много времени, и я только наполовину закончил его.Поэтому я написал это прямо в T-SQL.

Вот что мне удалось написать.Однако при работе с базой данных SQL Azure создается исключение тайм-аута.Я знаю, что это связано с ограничением DTU, но мне также интересно, можно ли улучшить этот запрос.Я не эксперт по SQL, и мне нужна ваша помощь.

Текущий запрос

DECLARE @maxSize int = 1
DECLARE @tempTable TABLE 
(
    Id uniqueidentifier,
    Size float,
    Position int
)
DECLARE @currentId uniqueidentifier
DECLARE @maxIterations int
DECLARE @index int = 1

SET @maxIterations = (SELECT COUNT(Id) FROM WhereToDelete)


WHILE(@index < @maxIterations)
BEGIN

    INSERT INTO @tempTable
    SELECT MasterJobGUID,   ISNULL(DATALENGTH(BlobColumn1),0) + 
                            ISNULL(DATALENGTH(BlobColumn2),0) + 
                            ISNULL(DATALENGTH(BlobColumn3),0) + 
                            ISNULL(DATALENGTH(BlobColumn4),0),
            @index
    FROM WhereToDelete
    ORDER BY SomeColumn
    OFFSET @index ROWS
    FETCH NEXT 1 ROWS ONLY

    SET @index=@index+1

    SET @currentid = (SELECT TOP 1 Id FROM @tempTable ORDER BY Position DESC)

    UPDATE @tempTable
    SET Size = Size + ( SELECT SUM(ISNULL(DATALENGTH(BlobColumn),0))
                        FROM LinkedTable
                        WHERE ParentId = @currentId )

    UPDATE @tempTable
    SET Size = Size + ( SELECT ISNULL(SUM(ISNULL(DATALENGTH(OtherBlobColumn),0)),0) 
                        FROM OtherLinkedTable
                        WHERE OtherLinkedTableId IN
                        (
                            SELECT OtherLinkedTableId FROM SomeTable
                            WHERE SomeTableId IN
                            (
                                SELECT SomeTableId FROM SomeOtherTable
                                WHERE ParentId = @currentId
                            )       
                        ))


    IF ((SELECT SUM(Size) FROM @tempTable) >= @maxSize*1000000)
    BEGIN
        BREAK;
    END
END

SELECT Id from @tempTable

1 Ответ

0 голосов
/ 29 января 2019

Вы можете попробовать что-то вроде этого

SELECT MasterJobGUID FROM (
    SELECT [MasterJobGUID], SUM(ISNULL(DATALENGTH(BlobColumn1),0) + 
                                ISNULL(DATALENGTH(BlobColumn2),0) + 
                                ISNULL(DATALENGTH(BlobColumn3),0) + 
                                ISNULL(DATALENGTH(BlobColumn4),0)) 
                            OVER (ORDER BY SomeColumn ROWS UNBOUNDED PRECEDING) SizeTotal 
      FROM WhereToDelete) innerQuery 
 WHERE [SizeTotal] < @maxSize*1000000

Это использует оконные функции T-SQL, чтобы вернуть вам суммарный общий размер, и возвращает только те строки, которые соответствуют критериям, в одной операции.Он должен быть более эффективным, чем курсор.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...