【.com快译】作为分析平台,Snowflake数据仓库(DataWarehouse)以超快的查询性能闻名于业界。但是,我们既不能为Snowflake建立索引,也不能捕获统计信息,也不能管理分区。那么,如何优化Snowflake数据库以获得更好的查询性能?本文将涵盖有关如何调整系统以获得最大吞吐量的三个主要方面,即:数据摄取、数据转换和最终用户查询。影响Snowflake查询性能的因素作为技术人员,我们经常需要在不真正了解问题时提出并实施解决方案。所以一般来说,我们在分析平台的性能问题时,通常会从以下三个方面入手:数据加载速度:应具备快速加载大量数据的能力。二.数据转换:它应该能够最大限度地提高吞吐量,并将原始数据快速转换成适合查询的格式。三.数据的查询速度:最大限度地减少每次查询的延迟并尽快向商业智能用户提供结果的能力。1.Snowflake加载数据避免扫描文件下图是最常见的批量加载数据到Snowflake的方法。这种方式主要是将数据从本地(on-premise)系统传输到云存储,然后使用COPY命令加载到Snowflake中。然后Snowflake在复制数据之前检查文件是否已经加载。这是通过将COPY限制到特定目录来最大化加载性能的第一种也是最简单的方法。以下代码片段显示了一系列COPY操作。SQL--最慢的方法:Scanentirestagecopyintosales_tablefrom@landing_datapattern='.*[.]csv';--最灵活的方法:Limitwithindirectorycopyintosales_tablefrom@landing_data/sales/transactions/2020/05pattern='.*[.]csv';--最快的方法:Anamedfile_fromsales_table/sales/交易/2020/05/sales_050.csv;可见,最快的方法是命名一个特定的文件,并使用通配符来体现其灵活性。当然,我们也可以在载入后立即删除目标文件。ResizingVirtualWarehousesandFiles下图展示了在将大型数据文件加载到Snowflake中时,设计人员倾向于横向扩展更大的虚拟仓库以加快整个加载过程。这是一个普遍的误解。事实上,在这种情况下,增加仓库的大小并不会带来任何性能优势。换句话说,上面的COPY语句会打开一个10Gb的数据文件,并使用某个线程依次加载一个节点上的数据,而其余的服务器保持空闲。通过基准测试,我们发现:通常,加载速率约为每分钟9Gb。我们可以尝试提高这个速度。下图显示了一种更好的方法——将单个10Gb文件分解为100个100Mb文件,以充分利用Snowflake的自动并行处理。2.Snowflake的转换性能延迟和吞吐量虽然优化SQL是减少时间开销最有效的方法,但设计人员通常不擅长计时。除了减少单个查询的延迟之外,最大化吞吐量(即:在尽可能短的时间内最大化数据交付)也非常重要。下图显示了一个典型的数据转换模式,它在虚拟仓库中执行一系列批处理作业。下一个任务只有在上一个任务完成后才会开始:我们很容易想到的解决方案是将其扩展成一个更大的虚拟仓库,以更快地完成作业任务。然而,这种解决方案往往受到硬件资源的限制。另外,虽然这样可以提高查询性能,但也会造成大量的仓库资源得不到充分利用。如上所示,ApacheAirflow可用于执行与Snowflake的多个独立连接。其中,每个线程都会对同一个虚拟仓库执行单个任务。随着工作负载的增加,如果可用资源不足,作业任务就会开始排队。为了分担负载,我们可以配置Snowflake的多集群功能,自动创建另一个同样大小的虚拟仓库。上述解决方案在任务完成时也自动收缩为单个集群,并具有在最长作业完成后暂停集群的能力。这是迄今为止获得自动缩放和收缩功能的最有效方法。以下SQL片段显示了创建多集群仓库所需的命令,该仓库将在60秒不活动后自动挂起。我们使用ECONOMYE扩展策略来提高吞吐量并节省单个查询的等待时间。SQL--Createamulti-clusterwarehouseforbatchprocessingcreateorreplacewarehousebatch_vwhwithwarehouse_size=SMALLmin_cluster_count=1max_cluster_count=10scaling_policy.=economyauto_suspend.=60initially_suspended=true;3.调整Snowflake的查询性能选择必要的列与许多其他数据分析平台类似,Snowflake也采用列式数据存储。如下图所示,存储经过优化以仅获取特定查询所需的那些属性,而不是所有列:在上图中,查询仅从具有数百列的表中获取两列。传统的行存储需要从磁盘读取所有列数据。显然,前者的效率要高得多。最大化缓存利用率下图展示了Snowflake内部架构的一个重要部分,它能够在虚拟仓库和云服务层之间缓存数据。商业智能仪表板可以通过重新执行相同的查询来刷新和显示更改的数据值。Snowflake通过返回最近24小时内查询到的ResultsCache的内容来实现对此类查询的自动调优。虽然数据也会缓存在快速SSD(固态硬盘)上的虚拟仓库中,但是和上面说的结果缓存不同的是,虚拟仓库是按照最近最少使用的原则来保存原始数据的,所以这样的数据很可能已经过期了。不过,虽然我们不能直接调整虚拟仓库中的缓存内容,但我们可以通过以下步骤对其进行优化:获取需要的属性:避免在查询中使用SELECT*,毕竟这会存储所有来自数据库的数据属性(DatabaseStorage)全部交给仓库缓存(WarehouseCache)。这不仅速度慢,而且还会导致不需要的数据也被填充到仓库缓存中。扩容:虽然我们应该避免扩容来处理特定的查询,但是我们需要调整仓库本身的大小来提高整体的查询性能。那些额外的服务器不仅可以分散突发任务的负担,还可以有效地增加仓库缓存的大小。考虑数据聚类:对于大于TB的数据表,请考虑创建聚簇键(clusterkey,参见--https://www.analytics.today/blog/tuning-snowflake-performance-with-clustering)最大化的方式消除分区(partition)。这样不仅可以提高单次查询的性能,还可以返回更少的微分区(micro-partitions),从而充分利用仓库缓存。SQL--Identifypotentialperformanceissuesselectquery_idasquery_id,round(bytes_scanned/1024/1024)asmb_scanned,total_elapsed_time/1000aselapsed_seconds,(partitions_scanned/nullif(partitions_total,0))*100aspct_table_scan,percent_scanned_from_cache*100aspct_fromcache,bytes_spilled_to_local_storageasspill_to_local,bytes_spilled_to_remote_storageasspill_to_remotefromsnowflake.account_usage.query_historywhere(bytes_spilled_to_local_storage>1024*1024orbytes_spilled_to_remote_storage>1024*1024orpercentage_scanned_from_cache<0.1)andelapsed_seconds>120andbytes_scanned>1024*1024orderbyelapsed_secondsdesc;上面的SQL代码段可以帮助我们识别那些运行时间超过2分钟,扫描了1MB数据的查询性能问题。下面两个方面特别值得我们注意:表扫描:在大数据表中,如果PCT_TABLE_SCAN的值比较高,或者MB_SCANNED的量比较大,说明查询的选择性比较差。因此,我们需要检查查询中的WHERE子句并适当考虑聚簇键。溢出:SPILL_TO_LOCAL或SPILL_TO_REMOTE中的任何值都表示系统对小型虚拟仓库执行了大型操作。因此,我们需要考虑将查询迁移到更大的仓库,或者适当扩展现有仓库。综上所述,业界对Snowflake的一个普遍误解是,直接扩展到更大的仓库是提高查询性能的唯一解决方案。但这在实践中不一定是一个很好的策略。我们需要明确问题是出在数据获取环节,还是出在数据转换部分,还是出在最终用户的查询上。毕竟设计可扩展的大仓库比简单的查询调整更适合提高数据库的查询性能。原标题:Top3SnowflakePerformanceTuningTactics,作者:JohnRyan
