添加 SELECT COUNT(*) 子条款会破坏 SQL 服务器中的性能
Adding SELECT COUNT(*) subclause trashes performance in SQL Server
我正在构建一个查询,最新的步骤涉及添加一个 SELECT COUNT(*) FROM [modification]
子句以允许我检测查询的最后一行,但这会破坏性能:
SELECT CONCAT(
IIF(row_number() OVER (ORDER BY forecastId) % 50000 = 1,
CONCAT('INSERT INTO modification (userId, epochTime, ',
'forecastId, description, auxText, auxDate) VALUES ('),
' ('),
userId, ',',
epochTime, ',',
forecastId, ',',
'''', dbo.encode4MySql(description), ''',',
'''', dbo.encode4MySql(auxText), ''',',
'''', CONVERT(VARCHAR(20), auxDate, 120), ''')',
IIF(row_number() OVER (ORDER BY forecastId) % 50000 = 0
OR row_number() OVER (ORDER BY forecastId) =
(SELECT COUNT(*) FROM modification),
'; COMMIT;', ','))
FROM modification
ORDER BY forecastId;
如果您看不到我在做什么,我正在构建 INSERT () VALUES (),(),(),...
一次 50000 行的语句。
请限制对评论的完全替代方法的建议。我正在寻找一种方法来找到最后一行号,而不会大幅降低查询速度 - 它确实如此。
我不太熟悉查询计划,但如果有帮助,可以 post 了解一下。我已经从相关问题中尝试了很多东西,但我无法开始工作。
你的表达式比较复杂,所以SQL服务器可能没有优化它。将逻辑移至 FROM
子句:
FROM (SELECT m.*, COUNT(*) OVER () as num_rows
FROM modification m
) m
然后在查询的其余部分使用 num_rows
。
假设您不想更改当前设计,您可以在最后添加一个额外的 UNION ALL 步骤。通过查看您的查询,更改查询的唯一目的似乎是在末尾添加一个 COMMIT。
CURRENT QUERY
UNION ALL
SELECT 'COMMIT;';
让我知道这是否适合你。
***********更新*********
我认为这个查询更容易解决问题。看看它是否会表现得更好。您必须为 table.
插入 CTE 部分
SELECT BusinessEntityID,JobTitle,HireDate INTO dbo.TestTable FROM [HumanResources].[Employee]
SELECT TOP 0 BusinessEntityID,JobTitle,HireDate INTO dbo.TestTable2 FROM [HumanResources].[Employee]
SET NOCOUNT ON
WITH CTE AS (SELECT ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) Col,
' (' +
CAST(BusinessEntityID AS VARCHAR(20)) +
', ''' +
JobTitle +
''', ''' +
CONVERT(VARCHAR(20), HireDate, 120) +
''')' Query
FROM TestTable
)
SELECT
CASE
WHEN COL % 50 = 0 THEN ', ' + Query + ' COMMIT;'
WHEN COL % 50 = 1 THEN ' INSERT INTO dbo.TestTable2 (BusinessEntityID, JobTitle, HireDate) VALUES ' + Query
ELSE ', ' + Query
END
FROM CTE
UNION ALL SELECT 'COMMIT;'
另一种选择是 order by forecastId desc
在最后 or
:
IIF(row_number() OVER (ORDER BY forecastId) % 50000 = 0
OR row_number() OVER (ORDER BY forecastId desc) = 1,
'; COMMIT;', ','))
我正在构建一个查询,最新的步骤涉及添加一个 SELECT COUNT(*) FROM [modification]
子句以允许我检测查询的最后一行,但这会破坏性能:
SELECT CONCAT(
IIF(row_number() OVER (ORDER BY forecastId) % 50000 = 1,
CONCAT('INSERT INTO modification (userId, epochTime, ',
'forecastId, description, auxText, auxDate) VALUES ('),
' ('),
userId, ',',
epochTime, ',',
forecastId, ',',
'''', dbo.encode4MySql(description), ''',',
'''', dbo.encode4MySql(auxText), ''',',
'''', CONVERT(VARCHAR(20), auxDate, 120), ''')',
IIF(row_number() OVER (ORDER BY forecastId) % 50000 = 0
OR row_number() OVER (ORDER BY forecastId) =
(SELECT COUNT(*) FROM modification),
'; COMMIT;', ','))
FROM modification
ORDER BY forecastId;
如果您看不到我在做什么,我正在构建 INSERT () VALUES (),(),(),...
一次 50000 行的语句。
请限制对评论的完全替代方法的建议。我正在寻找一种方法来找到最后一行号,而不会大幅降低查询速度 - 它确实如此。
我不太熟悉查询计划,但如果有帮助,可以 post 了解一下。我已经从相关问题中尝试了很多东西,但我无法开始工作。
你的表达式比较复杂,所以SQL服务器可能没有优化它。将逻辑移至 FROM
子句:
FROM (SELECT m.*, COUNT(*) OVER () as num_rows
FROM modification m
) m
然后在查询的其余部分使用 num_rows
。
假设您不想更改当前设计,您可以在最后添加一个额外的 UNION ALL 步骤。通过查看您的查询,更改查询的唯一目的似乎是在末尾添加一个 COMMIT。
CURRENT QUERY
UNION ALL
SELECT 'COMMIT;';
让我知道这是否适合你。
***********更新*********
我认为这个查询更容易解决问题。看看它是否会表现得更好。您必须为 table.
插入 CTE 部分SELECT BusinessEntityID,JobTitle,HireDate INTO dbo.TestTable FROM [HumanResources].[Employee]
SELECT TOP 0 BusinessEntityID,JobTitle,HireDate INTO dbo.TestTable2 FROM [HumanResources].[Employee]
SET NOCOUNT ON
WITH CTE AS (SELECT ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) Col,
' (' +
CAST(BusinessEntityID AS VARCHAR(20)) +
', ''' +
JobTitle +
''', ''' +
CONVERT(VARCHAR(20), HireDate, 120) +
''')' Query
FROM TestTable
)
SELECT
CASE
WHEN COL % 50 = 0 THEN ', ' + Query + ' COMMIT;'
WHEN COL % 50 = 1 THEN ' INSERT INTO dbo.TestTable2 (BusinessEntityID, JobTitle, HireDate) VALUES ' + Query
ELSE ', ' + Query
END
FROM CTE
UNION ALL SELECT 'COMMIT;'
另一种选择是 order by forecastId desc
在最后 or
:
IIF(row_number() OVER (ORDER BY forecastId) % 50000 = 0
OR row_number() OVER (ORDER BY forecastId desc) = 1,
'; COMMIT;', ','))