gpt4 book ai didi

sql - 如何减少SQL Server中的查询运行时间?

转载 作者:行者123 更新时间:2023-12-02 02:17:03 25 4
gpt4 key购买 nike

我编写了下面的查询来从两个不同的表中检索不同的 RegNo。但下面的查询需要近 25 秒才能检索结果。 Inventory表中有超过150万条记录。

Select F.PKID, F.RegNo
From
(
Select E.PKID, E.RegNo
Row_Number() Over(Order By E.RegNo Asc) RowNo
From
(
Select C.PKID, C.RegNo
From
(
Select Pk_Id PKID, LTrim(RTrim(A.Reg_No)) RegNo,
Row_Number() Over(Partition By LTrim(RTrim(A.Reg_No))
Order By (Select Null)) RegRowNo
From dbo.KeyreferenceDetails A (NoLock)
Where A.KeyreferenceStatus = 'L'
And A.Reg_No Like @Value And IsNull(Reg_No, '') <> '' And Not Exists
(
Select 1 From dbo.INVENTORY B (NoLock)
Where A.Reg_No = B.Inv_H_Reg_No
)
) C
Where C.RegRowNo = 1 And IsNull(C.RegNo, '') <> '-'
Union
Select D.PKID, D.RegNo
From
(
Select Pk_ID PKID, LTrim(LTrim(Txt_RegNo)) RegNo,
Row_Number() Over(Partition By LTrim(LTrim(A.Txt_RegNo))
Order By (Select Null)) RegRowNo
From dbo.MobileMessageDetails A (Nolock)
Left Join dbo.PLACE P (Nolock) On P.Place_Shrt_Code = A.Txt_YarddCode
And P.[Status] = 'L'
Left Join dbo.INVENTORY B (Nolock) On A.Txt_RegNo = B.Inv_H_Reg_No
Where A.Txt_INOUT In('IN', 'MOBILE') And IsNull(A.Txt_RegNo, '') <> '' And B.Inv_H_Pk_Id Is Null
And A.[Status] = 'L' And Txt_RegNo Like @Value
) D
Where D.RegRowNo = 1 And IsNull(D.RegNo, '') <> '-'
) E
) F
Where F.RowNo > 0 And F.RowNo <= 20

查询计划:

enter image description here

可用索引:

KeyreferenceDetails 表:

 Index Name ---------------+ Column Name ----------------- + Index Type
IX_KeyreferenceDetails_I | Reg_No | NONCLUSTERED
IX_KeyreferenceDetails_II | KeyreferenceStatus | NONCLUSTERED

库存表:

 Index Name ---------------+ Column Name ----------------- + Index Type
IX_Inventory_I | Inv_H_Reg_No | NONCLUSTERED

MobileMessageDetails 表:

 Index Name --------------- + Column Name ----------------- + Index Type
IX_MobileMessageDetails_I | Txt_RegNo | NONCLUSTERED
IX_MobileMessageDetails_II | Txt_INOUT | NONCLUSTERED

位置表:

 Index Name ---------------+ Column Name ----------------- + Index Type
IX_Place_I | Place_Shrt_Code | NONCLUSTERED
IX_Place_I | Status | NONCLUSTERED

我已经为上面查询中使用的所有表创建了所需的索引。但查询成本较高。如何减少SQL Server中的查询运行时间?

统计输出:

SQL Server Execution Times:
CPU time = 0 ms, elapsed time = 0 ms.
Table 'INVENTORY'. Scan count 6, logical reads 382, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'KeyreferenceDetails'. Scan count 15, logical reads 9062, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'Worktable'. Scan count 0, logical reads 0, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'Mobile_MessageDetails'. Scan count 1, logical reads 4, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table '#TempItemsCount_____________________________________________________________________________________________________0000000118A9'. Scan count 0, logical reads 1, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'Worktable'. Scan count 0, logical reads 0, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

SQL Server Execution Times:
CPU time = 20733 ms, elapsed time = 7844 ms.
Table 'INVENTORY'. Scan count 6, logical reads 382, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'KeyreferenceDetails'. Scan count 14, logical reads 9062, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'Worktable'. Scan count 0, logical reads 0, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'Mobile_MessageDetails'. Scan count 1, logical reads 4, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table '#VehicleRegDetails__________________________________________________________________________________________________0000000118AB'. Scan count 0, logical reads 20, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'Worktable'. Scan count 0, logical reads 0, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

SQL Server Execution Times:
CPU time = 21139 ms, elapsed time = 8146 ms.
Table '#TABLE_SCHEMA_______________________________________________________________________________________________________0000000118AA'. Scan count 0, logical reads 1, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

更新:

Insert Into #TempItemsCount(TotalCount)
Select Count(E.PKID)
From
(
Select E.PKID, E.RegNo
Row_Number() Over(Order By E.RegNo Asc) RowNo
From
(
Select C.PKID, C.RegNo
From
(
Select Pk_Id PKID, LTrim(RTrim(A.Reg_No)) RegNo,
Row_Number() Over(Partition By LTrim(RTrim(A.Reg_No))
Order By (Select Null)) RegRowNo
From dbo.KeyreferenceDetails A (NoLock)
Where A.KeyreferenceStatus = 'L'
And A.Reg_No Like @Value And IsNull(Reg_No, '') <> '' And Not Exists
(
Select 1 From dbo.INVENTORY B (NoLock)
Where A.Reg_No = B.Inv_H_Reg_No
)
) C
Where C.RegRowNo = 1 And IsNull(C.RegNo, '') <> '-'
Union
Select D.PKID, D.RegNo
From
(
Select Pk_ID PKID, LTrim(LTrim(Txt_RegNo)) RegNo,
Row_Number() Over(Partition By LTrim(LTrim(A.Txt_RegNo))
Order By (Select Null)) RegRowNo
From dbo.MobileMessageDetails A (Nolock)
Left Join dbo.PLACE P (Nolock) On P.Place_Shrt_Code = A.Txt_YarddCode
And P.[Status] = 'L'
Left Join dbo.INVENTORY B (Nolock) On A.Txt_RegNo = B.Inv_H_Reg_No
Where A.Txt_INOUT In('IN', 'MOBILE') And IsNull(A.Txt_RegNo, '') <> '' And B.Inv_H_Pk_Id Is Null
And A.[Status] = 'L' And Txt_RegNo Like @Value
) D
Where D.RegRowNo = 1 And IsNull(D.RegNo, '') <> '-'
) E
)

最佳答案

在没有模式和有限信息的情况下回答,因此不能保证这会解析,但下面是对其进行优化的尝试,以便您至少可以理解这些方法。

优化可以分为以下几点:

  1. 将复杂的查询分成单独的语句,这些语句更容易理解(对于人们和优化器来说)并且知道优化器会很好地处理。例如,优化第一个查询很容易,因为很明显 Reg_No用于JOIN以及 WHERE条款。索引示例可能是:

    创建非聚集索引index_name ON dbo.KeyreferenceDetails (Reg_No) INCLUDE (Pk_Id, KeyreferenceStatus) WHERE KeyreferenceStatus = 'L'

  2. 消除 ISNULL 中的函数( COALESCELTRIMRTRIMJOIN 等) , WHERE , PARTITION BY 。例如,考虑一下:

    WHERE ISNULL(A.Reg_No, '') <> ''

    优化器将无法使用 Reg_No 上的索引因为你正在对其应用一个函数。相反,将其重写为:

    WHERE A.Reg_No <> '' AND A.Reg_No IS NOT NULL

  3. 考虑使用UNION ALLUNION 。对于 UNION ,查询引擎将对两个集合进行去重并仅返回唯一的。它必须在返回任何数据进行处理之前执行此操作。与UNION ALL您有一个串联,可以简单地独立处理两个查询并将第二组查询附加到第一个查询的末尾。

  4. 而不是使用 INWHERE子句,您可以使用 LEFT OUTER JOIN并添加检查以查看连接表中的键列是否为 NULL,以确保没有从中返回任何记录,或者 EXISTS ,这通常会更有效地执行。

下面是将其中一些原则应用于查询的一种方法的示例:

IF OBJECT_ID('tempdb..#temp') IS NOT NULL DROP TABLE #temp;
GO
SELECT PKID = Pk_Id,
RegNo = LTrim(RTrim(A.Reg_No)),
RegRowNo = Row_Number() Over(Partition By LTrim(RTrim(A.Reg_No)) Order By (Select Null))
INTO #temp
FROM dbo.KeyreferenceDetails A WITH(NOLOCK)
LEFT OUTER JOIN dbo.INVENTORY B WITH(NOLOCK) ON A.Reg_No = B.Inv_H_Reg_No
WHERE B.Inv_H_Reg_No IS NULL
AND A.KeyreferenceStatus = 'L'
And A.Reg_No Like @Value
And A.Reg_No IS NOT NULL
AND A.Reg_No <> '';

INSERT INTO #temp (PKID, RegNo, RegRowNo)
SELECT PKID = Pk_ID,
RegNo = LTrim(LTrim(A.Txt_RegNo)),
RegRowNo = Row_Number() Over(Partition By LTrim(LTrim(A.Txt_RegNo)) Order By (Select Null))
FROM dbo.MobileMessageDetails A WITH(NOLOCK)
LEFT OUTER JOIN dbo.PLACE P WITH(NOLOCK) ON P.Place_Shrt_Code = A.Txt_YarddCode AND P.[Status] = 'L'
LEFT OUTER JOIN dbo.INVENTORY B WITH(NOLOCK) ON A.Txt_RegNo = B.Inv_H_Reg_No
WHERE B.Inv_H_Pk_Id Is Null
AND A.Status = 'L'
AND A.Txt_RegNo Like @Value
And A.Txt_RegNo IS NOT NULL
AND A.Txt_RegNo <> ''
AND A.Txt_INOUT In ('IN', 'MOBILE');

IF OBJECT_ID('tempdb..#final') IS NOT NULL DROP TABLE #final;
GO
SELECT t.PKID,
t.RegNo,
RowNo = Row_Number() Over(Order By t.RegNo Asc)
INTO #final
FROM #temp t;
WHERE t.RegNo <> '-'

SELECT F.PKID, F.RegNo
FROM #final F
WHERE F.RowNo BETWEEN 1 AND 20

GO
DROP TABLE #temp, #final

由于其中很可能存在语法错误,因此当您查看此内容时,我建议一次运行每个部分并确保其正常工作,而不是立即执行整个脚本。希望这有帮助!

问候,

罗斯

关于sql - 如何减少SQL Server中的查询运行时间?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36091357/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com