
# 在DWS点查询场景中使用bitmap index降低空间和写入成本
#### 场景介绍
在实际业务中，针对主键、订单号、用户ID等字段的点查场景较为常见，传统做法是通过建立索引来提升查询性能，这类方式在小数据量或高选择性字段上效果显著。
但在**大数据量、宽表结构或批量入库**场景下，常规索引机制逐渐暴露出以下问题：
- 索引结构维护成本高，空间占用大。
- 入库或更新性能受限，批量写入开销明显。
- 对于重复值较多的字段，索引命中率低，收益不明显。
为了解决这些问题，DWS对HStore表提供了轻量级的列级索引机制**bitmap index** ，在保证查询加速能力的同时，**最大程度降低空间和写入成本，特别适用于点查类字段的性能优化**。
在HStore表中，bitmap index索引机制会根据CU内的数据分布特征，灵活采用位图索引、字典编码、Bloom Filter等优化手段，构建轻量化索引结构与压缩方案。结合DWS的列存执行机制，可在保持极低空间开销的同时，有效提升点查类查询的执行效率，显著降低整体I/O成本。
该机制特别适用于高频点查、高重复值字段、冷热字段混合等场景，在提升性能的同时，有效控制存储成本。
#### 约束限制
- 该功能基于行列共存表实现，**仅9.1.1.100及以上版本支持**。
- 行列共存表其他约束限制参见[约束限制](https://support.huaweicloud.com/bestpractice-dws/dws_05_0030.html#ZH-CN_TOPIC_0000002436062520__section177419585814)。
 
#### 语法参考
如果要使用bitmap index功能，需要在建表的时候，指定相应的bitmap列（即使用bitmap_columns参数），才能生成bitmap index的映射关系。
以下是创建行列共存表且指定了bitmap列的语法，更多请参见[CREATE TABLE](https://support.huaweicloud.com/sqlreference-911-dws/dws_06_0177.html)语法章节（**仅9.1.1.100及以上版本支持**）。
```
CREATE TABLE <表名> (
    <列定义>
)
WITH (
    orientation = column,          -- 基于列式的存储架构
    enable_hstore_opt = on,        -- 开启 hstore_opt 能力
    storage_mode = 'mix'           -- 指定建立行列共存表
    bitmap_columns = 'a'           --指定用来做bitmap的列名，例如a列。
);
```
#### 使用示例
1. 使用客户端连接DWS，构造数据表。 
   数据量较多，请等待约1分钟。
   ```
   DROP TABLE IF EXISTS data;
   CREATE TABLE data(a INT, b BIGINT, c VARCHAR(10), d VARCHAR(10));
   INSERT INTO data values(generate_series(1,60000),1,'asdfasdf','gergqer');
   INSERT INTO data select * from data;
   INSERT INTO data select * from data;
   INSERT INTO data select * from data;
   INSERT INTO data select * from data;
   INSERT INTO data select * from data;
   ```
   
   
2. 构造一个简单的行列共存Mix模式表。 
   ```
   DROP TABLE IF EXISTS mixmode_test1;
   CREATE TABLE mixmode_test1 (
       a INT,
       b BIGINT,
       c VARCHAR(10),
       d VARCHAR(10)
   )
   WITH (
       orientation = column,
       enable_hstore_opt = on,
       storage_mode = 'mix',
       bitmap_columns = 'a'    --指定a列为bitmap列
   );
   ```
   
   
3. 创建B-Tree索引。 
   ```
   CREATE INDEX idx_data_a_btree ON mixmode_test1(a);
   ```
   
   
4. 将数据导入行列共存Mix模式表。 
   ```
   INSERT INTO mixmode_test1 SELECT * FROM data;
   ```
   
   
5. 使用索引扫描进行点查，查找a = 42的记录, 打印执行计划。 
   ```
   SET enable_seqscan = off;      --关闭顺序扫描
   SET enable_indexscan = on;     --使用索引扫描
   SET enable_fast_query_shipping = off;   --优化器使用分布式框架，即执行计划在CN上生成，再发送到DN中执行。
   EXPLAIN PERFORMANCE SELECT * FROM mixmode_test1 WHERE a = 42;
   ```
   从执行计划结果判断，执行器选择了索引扫描。
   ![](https://support.huaweicloud.com/bestpractice-dws/figure/zh-cn_image_0000002475087669.png "点击放大")
   
   
6. 使用顺序扫描进行点查，查找a = 42的记录, 打印执行计划。 
   ```
   SET enable_seqscan = on;       --打开顺序扫描
   SET enable_indexscan = off;    --关闭索引扫描
   SET enable_bitmapscan = off;   --关闭bitmap扫描
   SET enable_fast_query_shipping = off;      --优化器使用分布式框架，即执行计划在CN上生成，再发送到DN中执行。
   EXPLAIN PERFORMANCE SELECT * FROM mixmode_test1 WHERE a = 42;
   ```
   从执行计划结果判断，使用bitmap_column点查执行计划中选择了顺序扫描，可以看到Auto Index过滤掉绝大部分数据。
   ![](https://support.huaweicloud.com/bestpractice-dws/figure/zh-cn_image_0000002441528864.png "点击放大")
   
   
 
