SQL服务器查询改进建议,一次查询聚合大量数据
SQL Server query improvement suggestion, aggregation of large amount of data in a query
我的 BI 开发人员写了一个查询 运行 花了 14 个小时,我正在努力帮助他。在高层次上,这是一个探索过去 15 年的金融交易并将其细分为每个季度的查询。
我在这里分享我已经给他的答案,但我想知道您是否有任何建议我们可以进一步探索和研究以提高性能,回答如:“也许你可能想看看在快照.."
他的查询包括:
- 包括使用多个视图,意思是 select 从一个视图生成另一个视图等。
- 一些视图连接三个 table,每个视图有大约 100 - 2 亿行。
- 某些视图使用子 select 查询。
到目前为止,这是我的建议:
- 不要使用嵌套视图生成查询,而是使用视图为每个视图创建新的 tables,因为数据不是动态的(金融交易数据)并且不会改变。根据我的经验,嵌套视图不利于性能。
- 不要使用子查询,尽可能使用 JOIN。
- 我确保他在适当的时候创建非聚簇索引。
- 当有这么多数据时,不要使用 TEMPT table。
- 尝试在 JOIN
中使用的所有 table 上使用 WITH(NO LOCK)
- 找到一个常见的查询并将其转换为存储过程
- 加入这三个大 table 时(100 - 2 亿行),尝试限制
JOIN
处的数据量,而不是使用 WHERE
。例如,而不是 select * from tableA JOIN tableB WHERE... ,使用 SELECT * FROM TableA JOIN tableB ON .... AND tableA.date BETWEEN 范围。这将在查询稍后与其他 table 连接时提供较少的数据。
问题是他要处理的数据太大了,我想知道查询性能只能做这么多,因为归根结底,您仍然必须在查询中处理所有这些数据。也许下一步是考虑如何准备这些数据并首先将它们存储在较小的 table 中,例如 CostQ1_2010、CostQ2_2020 等...然后根据所有内容编写查询那些 tables.
你给我们提供的信息很少。托尔斯泰写道:“幸福的家庭都是相似的,不幸的家庭各有各的不幸。” SQL 查询也是如此,尤其是大型 BI 查询。
我会冒险给出一些笼统的答案。
对于您提到的大小的表,您的查询肯定包含 transaction_date >= something AND transaction_date < anotherthing
之类的日期范围 WHERE 过滤器。一般来说,一份有用的报告涵盖了十年交易中的一年。因此,请确保您有正确的索引以尽可能进行索引范围扫描。 SSMS,如果您选择“显示实际执行计划”功能,有时会建议索引。
学习阅读执行计划。
阅读覆盖索引。他们有时会产生很大的不同。
在开始这种长运行的历史BI查询之前使用语句SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED
。您将减少 BI 查询与数据库上其他 activity 之间的干扰。
从 BI 查询中使用的视图预加载一些非规范化表可能有意义。
我的 BI 开发人员写了一个查询 运行 花了 14 个小时,我正在努力帮助他。在高层次上,这是一个探索过去 15 年的金融交易并将其细分为每个季度的查询。
我在这里分享我已经给他的答案,但我想知道您是否有任何建议我们可以进一步探索和研究以提高性能,回答如:“也许你可能想看看在快照.."
他的查询包括:
- 包括使用多个视图,意思是 select 从一个视图生成另一个视图等。
- 一些视图连接三个 table,每个视图有大约 100 - 2 亿行。
- 某些视图使用子 select 查询。
到目前为止,这是我的建议:
- 不要使用嵌套视图生成查询,而是使用视图为每个视图创建新的 tables,因为数据不是动态的(金融交易数据)并且不会改变。根据我的经验,嵌套视图不利于性能。
- 不要使用子查询,尽可能使用 JOIN。
- 我确保他在适当的时候创建非聚簇索引。
- 当有这么多数据时,不要使用 TEMPT table。
- 尝试在 JOIN 中使用的所有 table 上使用 WITH(NO LOCK)
- 找到一个常见的查询并将其转换为存储过程
- 加入这三个大 table 时(100 - 2 亿行),尝试限制
JOIN
处的数据量,而不是使用WHERE
。例如,而不是 select * from tableA JOIN tableB WHERE... ,使用 SELECT * FROM TableA JOIN tableB ON .... AND tableA.date BETWEEN 范围。这将在查询稍后与其他 table 连接时提供较少的数据。
问题是他要处理的数据太大了,我想知道查询性能只能做这么多,因为归根结底,您仍然必须在查询中处理所有这些数据。也许下一步是考虑如何准备这些数据并首先将它们存储在较小的 table 中,例如 CostQ1_2010、CostQ2_2020 等...然后根据所有内容编写查询那些 tables.
你给我们提供的信息很少。托尔斯泰写道:“幸福的家庭都是相似的,不幸的家庭各有各的不幸。” SQL 查询也是如此,尤其是大型 BI 查询。
我会冒险给出一些笼统的答案。
对于您提到的大小的表,您的查询肯定包含 transaction_date >= something AND transaction_date < anotherthing
之类的日期范围 WHERE 过滤器。一般来说,一份有用的报告涵盖了十年交易中的一年。因此,请确保您有正确的索引以尽可能进行索引范围扫描。 SSMS,如果您选择“显示实际执行计划”功能,有时会建议索引。
学习阅读执行计划。
阅读覆盖索引。他们有时会产生很大的不同。
在开始这种长运行的历史BI查询之前使用语句SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED
。您将减少 BI 查询与数据库上其他 activity 之间的干扰。
从 BI 查询中使用的视图预加载一些非规范化表可能有意义。