
# 如何调整DWS分布列？
在数据仓库类型的数据库中，大表的分布列选择对于数据库和语句查询性能都有至关重要的影响。 如果表的分布列选择不当，在数据导入后有可能出现数据分布倾斜，进而导致某些磁盘的使用明显高于其他磁盘，极端情况下会导致集群只读。对于Hash分表策略，存在数据倾斜情况下，查询时出现部分DN的I/O短板，从而影响整体查询性能。合理的选择分布列，并对已经创建的表，进行分布列的调整，对表查询的性能至关重要。
采用Hash分表策略之后需对表的数据进行数据倾斜性检查，以确保数据在各个DN上是均匀分布的。一般来说，不同DN的数据量相差5%以上即可视为倾斜，如果相差10%以上就必须要调整分布列。
针对分布不均匀的表，尽可能通过调整分布列，以减少数据倾斜，避免带来潜在的数据库性能问题。
#### 选择合适的分布列
Hash分布表的分布列选取至关重要，需要满足以下基本原则：
- 列值应比较离散，以便数据能够均匀分布到各个DN。例如，考虑选择表的主键为分布列，如在人员信息表中选择身份证号码为分布列。
- 在满足第一条原则的情况下尽量不要选取存在常量filter的列。
- 在满足前两条原则的情况，考虑选择查询中的连接条件为分布列，以便Join任务能够下推到DN中执行，且减少DN之间的通信数据量。
- 支持多分布列特性，可以更好地满足数据分布的均匀性要求。
 
#### 如何调整
通过**select version();**语句查询当前数据库版本号，版本号不同，调整的方式不同：
![](https://support.huaweicloud.com/dws_faq/figure/zh-cn_image_0000001330488884.png "点击放大")
- **8.0.x及以前版本，通过重建表时指定分布列来调整**：
1. 通过Data Studio或者Linux下使用gsql访问数据库。
2. 创建新表。 
   ![](https://support.huaweicloud.com/dws_faq/public_sys-resources/note_3.0-zh-cn.png)
   以下步骤语句中，table1为原表名，table1_new为新表名，column1和column2为分布列名称。
   ```
   CREATE TABLE IF NOT EXISTS table1_new 
   ( LIKE table1 INCLUDING ALL EXCLUDING DISTRIBUTION) 
   DISTRIBUTE BY 
   HASH (column1, column2);
   ```
   
   
3. 迁移数据到新表。 
   ```
   START TRANSACTION;
   LOCK TABLE table1 IN ACCESS EXCLUSIVE MODE;
   INSERT INTO table1_new SELECT * FROM table1;
   COMMIT;
   ```
   
   
4. 查看表数据是否迁移成功，删除原表。 
   ```
   SELECT COUNT(*) FROM table1_new;
   DROP TABLE table1;
   ```
   
   
5. 替换原表。 
   ```
   ALTER TABLE table1_new RENAME TO table1;
   ```
   
   
- **8.1.0及以上版本**，通过ALTER TABLE语法进行调整，以下为示例。
1. 查询当前表定义，返回结果显示该表分布列为c_last_name。 
   ```
   SELECT pg_get_tabledef('customer_t1');
   ```
   ![](https://support.huaweicloud.com/dws_faq/figure/zh-cn_image_0000001248712703.png "点击放大")
   
   
2. 更新分布列中的数据时报错。 
   ```
   UPDATE customer_t1 SET c_last_name = 'Jimy' WHERE c_customer_sk = 6885;
   ```
   ![](https://support.huaweicloud.com/dws_faq/figure/zh-cn_image_0000001204596316.png "点击放大")
   
   
3. 将该表的分布列修改为不会更新的列，例如c_customer_sk。 
   ```
   ALTER TABLE customer_t1 DISTRIBUTE BY hash (c_customer_sk);
   ```
   ![](https://support.huaweicloud.com/dws_faq/figure/zh-cn_image_0000001248996617.png "点击放大")
   
   
4. 重新执行更新旧的分布列的数据。更新成功。 
   ```
   UPDATE customer_t1 SET c_last_name = 'Jimy' WHERE c_customer_sk = 6885;
   ```
   ![](https://support.huaweicloud.com/dws_faq/figure/zh-cn_image_0000001248717121.png "点击放大")
   
   
 
