如何提高动态构建的性能 SQL
How to improve performance of the dynamically build SQL
实际上,当我们通过 java 代码动态创建 SQL 时,我遇到了一些问题,这意味着在 where 中使用的字段列表不一致放置正确索引的子句存在巨大的延迟和性能损失。我们使用 MSSql 服务器作为历史数据的存储。目前记录总量300万条,以后肯定会增加。有没有办法优化以下 SQL 查询。非常感谢任何帮助,因为我无法将索引添加到所有可能的字段组合中,有 10 个以上。
SELECT
F_ID,
F_2,
F_3,..., F_15 FROM T_1 WHERE ~dynamically changed~
UNION ALL
SELECT
F_ID,
F_2,
F_3,..., F_15 FROM T_2 WHERE ~dynamically changed~
ORDER BY F_ID OFFSET 75 ROWS FETCH NEXT 25 ROWS ONLY`
`SELECT COUNT(*)
FROM (SELECT F_ID
FROM T_1
WHERE ~dynamically changed~
UNION ALL SELECT F_ID
FROM T_2
WHERE ~dynamically changed~) clause
现在我有唯一的索引 ~ 聚簇 ID 索引。没什么用。
如果不了解有关相关字段和其中数据的更多信息,则无法很好地回答这个问题,但这里有一些建议。
您不需要为 10 个以上的字段创建组合索引,您可以创建一个包含每个单独字段的索引。这很容易实现,但当然在存储系统上需要更多 space。有些字段的索引没有多大意义,例如仅包含两个不同值的字段(布尔值,通过包含值 0
和 1
等用作布尔值的 int 字段)
打印出缓慢的查询并使用 MS SQL 的查询分析器对其进行分析。 Microsoft 有一个 TechNet article 解释了如何做到这一点。
根据给定的信息,您可以决定优化查询的最佳方法,即需要添加什么索引来加快速度。
您似乎在 SQL 内对结果进行分页。您可能会检查这是否可以在您用于演示的编程语言中完成。在这种情况下,您可以打开一个游标并遍历数据,使语句只需要执行一次(第三条语句只计算要显示的所有条目的数量,游标免费提供)。
所以我为解决这个问题所做的是
创建了几个索引,其中包含最常用的和几乎唯一的字段,包括过滤器中使用的其余字段,这可以防止不必要的内部连接来获取 where 子句中不是 a 的数据索引的一部分
CREATE INDEX IX_1 ON table_placeholder (F_1) INCLUDE (F_2, F_3, F_4);
CREATE INDEX IX_2 ON table_placeholder (F_2) INCLUDE (F_1, F_3, F_4);
更改了现有查询,以便先执行 limit/filter 操作,然后再将连接应用于有限的数据集。在这个阶段,查询计划是您优化的唯一朋友。在我的特定示例中,新创建的查询看起来像
WITH cte AS (
SELECT id, tbl FROM (
SELECT
F_ID as id,
1 AS tbl
FROM T_1 WHERRE ~dynamically changed ~
UNION ALL
SELECT
F_ID as id,
2 AS tbl
FROM T_2 WHERE ~dynamically changed ~) as t
ORDER BY id
OFFSET :offset ROWS FETCH NEXT :size ROWS ONLY)
SELECT
F_ID,
F_2,
F_3,..., F_15
FROM cte
INNER JOIN T_1 ON cte.id = F_ID AND tbl = 1
UNION ALL
SELECT
F_ID,
F_2,
F_3,..., F_15
FROM cte
INNER JOIN T_2 ON cte.id = F_ID AND tbl = 2;
实际上,当我们通过 java 代码动态创建 SQL 时,我遇到了一些问题,这意味着在 where 中使用的字段列表不一致放置正确索引的子句存在巨大的延迟和性能损失。我们使用 MSSql 服务器作为历史数据的存储。目前记录总量300万条,以后肯定会增加。有没有办法优化以下 SQL 查询。非常感谢任何帮助,因为我无法将索引添加到所有可能的字段组合中,有 10 个以上。
SELECT
F_ID,
F_2,
F_3,..., F_15 FROM T_1 WHERE ~dynamically changed~
UNION ALL
SELECT
F_ID,
F_2,
F_3,..., F_15 FROM T_2 WHERE ~dynamically changed~
ORDER BY F_ID OFFSET 75 ROWS FETCH NEXT 25 ROWS ONLY`
`SELECT COUNT(*)
FROM (SELECT F_ID
FROM T_1
WHERE ~dynamically changed~
UNION ALL SELECT F_ID
FROM T_2
WHERE ~dynamically changed~) clause
现在我有唯一的索引 ~ 聚簇 ID 索引。没什么用。
如果不了解有关相关字段和其中数据的更多信息,则无法很好地回答这个问题,但这里有一些建议。
您不需要为 10 个以上的字段创建组合索引,您可以创建一个包含每个单独字段的索引。这很容易实现,但当然在存储系统上需要更多 space。有些字段的索引没有多大意义,例如仅包含两个不同值的字段(布尔值,通过包含值
0
和1
等用作布尔值的 int 字段)打印出缓慢的查询并使用 MS SQL 的查询分析器对其进行分析。 Microsoft 有一个 TechNet article 解释了如何做到这一点。 根据给定的信息,您可以决定优化查询的最佳方法,即需要添加什么索引来加快速度。
您似乎在 SQL 内对结果进行分页。您可能会检查这是否可以在您用于演示的编程语言中完成。在这种情况下,您可以打开一个游标并遍历数据,使语句只需要执行一次(第三条语句只计算要显示的所有条目的数量,游标免费提供)。
所以我为解决这个问题所做的是
创建了几个索引,其中包含最常用的和几乎唯一的字段,包括过滤器中使用的其余字段,这可以防止不必要的内部连接来获取 where 子句中不是 a 的数据索引的一部分
CREATE INDEX IX_1 ON table_placeholder (F_1) INCLUDE (F_2, F_3, F_4);
CREATE INDEX IX_2 ON table_placeholder (F_2) INCLUDE (F_1, F_3, F_4);更改了现有查询,以便先执行 limit/filter 操作,然后再将连接应用于有限的数据集。在这个阶段,查询计划是您优化的唯一朋友。在我的特定示例中,新创建的查询看起来像
WITH cte AS (
SELECT id, tbl FROM (
SELECT
F_ID as id,
1 AS tbl
FROM T_1 WHERRE ~dynamically changed ~
UNION ALL
SELECT
F_ID as id,
2 AS tbl
FROM T_2 WHERE ~dynamically changed ~) as t
ORDER BY id
OFFSET :offset ROWS FETCH NEXT :size ROWS ONLY)
SELECT
F_ID,
F_2,
F_3,..., F_15
FROM cte
INNER JOIN T_1 ON cte.id = F_ID AND tbl = 1
UNION ALL
SELECT
F_ID,
F_2,
F_3,..., F_15
FROM cte
INNER JOIN T_2 ON cte.id = F_ID AND tbl = 2;