SQL删除Azure的查询优化

时间:2019-01-29 09:36:23

标签: c# sql-server azure-sql-database

我需要一些有关优化以下查询的帮助。

  

我的问题

我正在尝试根据 size 参数清理表。 (从此表中删除x Mb)。我认为实现它的方式是:对表进行迭代,从最早的条目开始,获取每个行的大小(我只考虑blob列),对所有链接的表进行迭代,并对它们执行相同的操作; if currentSize >= size停止查询并返回找到的GUIDs的列表

请注意,这是一个较大查询的一部分,因此最后我需要Ids列表。

  

我尝试过的

首先,我尝试使用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 :(得分:0)

您可以尝试这样的事情

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窗口函数返回总大小的总和,并且仅在单个操作中返回符合条件的行。它应该比游标更有效。