
# DWS中"算子下盘"是什么含义？
用户业务查询执行过程中，当集群内存不足时，数据库可能会选择将临时结果暂存到磁盘。当临时结果的磁盘存储量超过一定值后，用户会收到告警"查询语句触发下盘量超阈值"，那这个告警中的"下盘量"或者数据库中经常出现的"算子下盘"如何理解呢？
#### 算子下盘的概念
任何计算都需要耗费内存空间，差别在于多少而已，如果耗费内存过多，会导致其他作业运行内存空间不足，导致作业不稳定，因此需要对查询语句的作业内存使用进行限制，保证作业运行的稳定性。
假如作业想要使用500M内存，但实际上因为内存限制最终只分配到300M内存，则需要把临时不用的数据写到磁盘上，内存中只保留正在使用的数据，这就是中间数据落盘的由来。当发生中间数据落盘时，称之为**算子下盘**。算子落盘空间太大除了会对查询性能有较大影响，还有可能导致数据库只读甚至磁盘满，因此DWS提供了用户算子空间限制，可以限制用户算子落盘的大小，在超限时查询报错退出。
#### 哪些算子会发生下盘
当前DWS可下盘算子有六类（向量化及非向量化共10种）：Hash(VecHashJoin)，Agg(VecAgg)，Sort(VecSort)，Material(VecMaterial)， SetOp(VecSetOp)，WindowAgg(VecWindowAgg)。
#### 哪些参数可以控制下盘
- work_mem：可以判断执行作业可下盘算子是否触发下盘阈值，当内存使用超过该参数后将触发算子下盘。该参数仅在非内存自适应场景（enable_dynamic_workload=off）时生效。work_mem参数设置通常是一个权衡，即要保证并发的吞吐量，又要保证单查询作业的性能，故需要根据实际执行情况（结合Explain Performance输出）进行调优。
- temp_file_limit：可以限制落盘算子的落盘文件大小，一般建议根据实际情况设置，防止下盘文件将磁盘空间占满，超过该值将报错退出。
 
#### 如何判断语句是否发生了下盘
- 通过下盘文件确认：下盘文件位于实例目录的base/pgsql_tmp路径下，下盘文件以*pgsql_tmp$queryid_$pid*命名，可以根据queryid确认是哪条SQL发生了下盘。
- 根据等待视图（pgxc_thread_wait_status）确认：等待视图中，当出现write file时，表示发生了中间结果下盘。
- 根据执行计划确认（explain performance）：performance中出现spill、written disk、temp file num等关键字时，说明对应的算子出现了下盘。
- 根据topsql确认（前提：topsql功能已开启）：[实时TopSQL语句](https://support.huaweicloud.com/devg-dws/dws_04_0397.html)或[历史TopSQL语句](https://support.huaweicloud.com/devg-dws/dws_04_0398.html)中，spill_info字段中会包含下盘信息，如果该字段不为空，说明有DN实例出现了下盘。
 
#### 如何避免下盘
发生算子下盘时，算子运算数据将写入磁盘，由于磁盘操作相对内存访问缓慢导致性能下降，查询响应时间出现极大劣化，因此应尽可能避免查询执行过程中的算子下盘，建议使用以下方法：
- 减小中间结果集：发生下盘时往往是由于中间结果集过大，因此可以增加过滤条件减少中间结果集大小。
- 避免数据倾斜：数据倾斜严重时会导致单DN上数据量过大，引起单DN下盘。
- 及时analyze：当统计信息不准时，行数估算可能偏小，导致计划选择非最优，从而出现下盘。
- 单点调优：对业务SQL进行单点调优。
- 非内存自适应场景下，当中间结果集无法减少时，应根据实际情况适当调大work_mem参数。
- 内存自适应场景下，内存使用配置要使得数据库可用内存尽量增大，减少下盘概率。
 
