如何优化我的功能以减少时间?

Sam*_*ror 2 sql sql-server

我正在执行 SQL 查询

SELECT Id, COMMENT 
FROM student 
WHERE dbo.Remove (COMMENT) like '%N8AABENAABEPIVAA#GVCIZNV';
Run Code Online (Sandbox Code Playgroud)

这是Remove函数:

CREATE FUNCTION [dbo].[Remove] 
    (@StringData VARCHAR(255))
RETURNS VARCHAR(200)
AS
BEGIN
    DECLARE @word VARCHAR(200) = '';

    WITH Numbers AS 
    (
        SELECT TOP (LEN(@StringData )) ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) AS N
        FROM master.dbo.spt_values
    )
    SELECT @word += SUBSTRING(@StringData, N, 1)
    FROM Numbers
    WHERE (N - 1) % 4 <> 0;

    RETURN @word;
Run Code Online (Sandbox Code Playgroud)

我尝试了这个函数,它返回的结果很好,但是当应用于 1'000'000 行时,它需要很多时间 - 大约 40 秒。

如何优化此功能以花费更少的时间或以任何其他方式执行相同的操作?

Cha*_*ace 5

您可以进行以下改进。

  • 使用内联表值函数而不是标量函数。
  • 使用GENERATE_SERIES代替spt_valuesROW_NUMBER
  • 使用STRING_AGG而不是变量合并来聚合。
CREATE OR ALTER FUNCTION [dbo].[Remove] (@StringData VARCHAR(255))
RETURNS TABLE
AS RETURN

SELECT
  word = STRING_AGG(SUBSTRING(@StringData, g.value, 1), '') WITHIN GROUP (ORDER BY g.value)
FROM GENERATE_SERIES(1, LEN(@StringData)) g
WHERE (g.value - 1) % 4 <> 0;
Run Code Online (Sandbox Code Playgroud)

要执行它,您不能直接在表达式中使用。你需要APPLY它。

SELECT
  Id,
  COMMENT
FROM student s
CROSS APPLY dbo.Remove(COMMENT) r
WHERE r.word like '%N8AABENAABEPIVAA#GVCIZNV';
Run Code Online (Sandbox Code Playgroud)

GENERATE_SERIES 仅在 SQL2022 或 Azure SQL 上受支持,否则请使用数字生成器,请参阅https://sqlperformance.com/2021/01/t-sql-queries/number-series-solutions-1


说了这么多,似乎您可以按照在中使用通配符的方式做一些事情LIKE

WHERE s.COMMENT LIKE '%N8A_ABE_NAA_BEP_IVA_A#G_VCI_ZNV'
Run Code Online (Sandbox Code Playgroud)