Dee*_*pak 7 sql-server ssis partitioning
我试图了解提高客户给我的查询性能的最佳方法。它包含几个连接的表,其中一个被称为dwh.fac_sale_detail
包含 15 亿行的表。
该表dwh.fac_sale_detail
根据其名为 的列之一进行分区TradingDateKey1
。它实际上以 yyyymmdd 格式存储数据,但它是INT
Datatype。
这有从 2005 年到 2015 年的 TradingDateKeys,但分区只创建到 2014 年。
另一个团队中的一个人提出了以下建议,我正在尝试遵循他的建议,但我是创建或更改分区的新手,不知道这是否真的会对查询性能产生任何影响:
他用他自己的话来说是“该FactSalesDetail
表目前大约有 15 亿行,目前TradingDate
按年划分为 10 个分区,每个分区大约有 1.5 亿行。最好将最近一年进一步划分为月分区并在所有分区上应用列存储索引。在每个分区上应用索引将是一次性的,您应该只需要维护当前分区的索引。”
这是我尝试优化的查询的查询计划。
另请参阅随附的屏幕截图以更好地理解:
Geo*_*son 12
感谢添加查询计划;这是非常有用的信息。我有一些基于查询计划的建议,但首先要注意:不要只接受我所说的并假设它是正确的,首先尝试一下(最好在您的测试环境中)并确保您了解更改的原因或者不要改进您的查询!
查询计划:概述
从这个查询计划(以及相应的 XML)中,我们可以立即看到一些有用的信息:
优化:列存储与否
这是一个棘手的问题,但总的来说,在这种情况下,我不会为您推荐列存储。主要原因是您使用的是 SQL 2012,所以如果您能够升级到 SQL 2014,我认为可能值得尝试列存储。
通常,您的查询是专为列存储设计的类型,并且可以从列存储减少的 I/O 和批处理模式更高的 CPU 效率中受益匪浅。
但是,SQL 2012中列存储的局限性太大了,并且tempdb 溢出行为,其中任何溢出都会导致 SQL Server 完全放弃批处理模式,这可能是一种毁灭性的惩罚,可能会对您处理的大量行产生影响。正在与。如果您确实在 SQL 2012 上使用列存储,请准备好密切关注您的所有查询,并确保始终可以使用批处理模式。
优化:更多分区?
我认为更多的分区不会帮助这个特定的查询。当然,欢迎您尝试,但请记住,分区主要是一种数据管理功能(通过SWITCH PARTITION
而不是性能功能在 ETL 过程中交换新数据的能力。它在某些情况下显然可以帮助提高性能,但同样地,它会损害其他方面的性能(例如,许多单例搜索现在每个分区必须执行一次)。
如果您确实使用列存储,我认为加载数据以更好地消除段将比分区更重要;理想情况下,您可能希望每个分区中的行尽可能多,以便拥有完整的列存储段和出色的压缩率。
优化:改进基数估计
因为您有一个巨大的事实表和来自每个维度表的少量非常小的(数百或数千行)行集,所以我建议您使用一种方法明确创建一个临时表,其中仅包含您计划使用的维度行. 例如,您应该编写一个预处理查询以仅提取您关心的行,并将适当的 PK 添加到这些行,而不是Dim_Date
使用像 那样的复杂逻辑连接。cast(right(ALHDWH.dwh.Dim_Date.Financial_Year,4) as int) IN ( 2015, 2014, 2013, 2012, 2011 )
Dim_Date
这将允许 SQL Server 仅对您实际使用的行创建统计信息,这可能会在整个计划中产生更好的基数估计。由于与整体查询复杂性相比,这种预处理的工作量非常小,因此我强烈推荐此选项。
优化:减少螺纹歪斜
很可能从Dim_Date
它自己的表中提取数据并向该表添加主键也有助于减少线程倾斜(跨线程的工作不平衡)。这是一张有助于说明原因的图片:
在本例中,该Dim_Date
表有 22,000 行,SQL Server 估计您将使用其中的 7,700 行,而您实际上只使用了其中的 1,827 行。
因为 SQL Server 使用统计信息来将行范围分配给线程,所以在这种情况下基数估计很差可能是行分布很差的根本原因。
1,872 行上的线程倾斜可能无关紧要,但痛苦的一点是,这会向下级联到 15 亿行事实表中的查找,其中我们有 30 个线程闲置,而 6 亿行正在由 2 个线程处理。
优化:摆脱排序溢出
我要关注的另一个领域是排序溢出。我认为在这种情况下的主要问题是基数估计不佳。正如我们在下面看到的,SQL Server 认为由 aSort
和a 组合执行的分组操作Stream Aggregate
将产生 3.24 亿行。然而,它实际上只产生 643,000 行。
如果 SQL Server 知道从这个分组中出来的行很少,它几乎肯定会使用HASH GROUP
(Hash Aggregate) 而不是SORT GROUP
(Sort-Stream) 来实现您的GROUP BY
子句。
如果您进行上述其他一些更改以改进基数估计,这可能会自行解决。但是,如果没有,您可以尝试使用OPTION (HASH GROUP)
查询提示来强制 SQL Server 这样做。这将让您评估改进的幅度并决定是否在生产中使用查询提示。我通常会对查询提示持谨慎态度,但HASH GROUP
与使用连接提示、使用FORCE ORDER
或以其他方式从查询优化器手中夺走太多控制权相比,指定只是轻而易举。
优化:内存授予
最后一个潜在问题是 SQL Server 估计查询需要使用 72GB 的内存,但您的服务器无法为查询提供这么多内存。虽然从技术上讲,向服务器添加更多内存会有所帮助,但我认为至少还有其他几种方法可以解决这个问题:
Sort
操作符(如上所述);它确实是唯一一个在查询中消耗大量内存的运算符 归档时间: |
|
查看次数: |
2166 次 |
最近记录: |