我需要一些有关优化以下查询的帮助。
我的问题
我正在尝试根据 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
答案 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窗口函数返回总大小的总和,并且仅在单个操作中返回符合条件的行。它应该比游标更有效。