
# Index Scan
#### 算子说明
在索引扫描中，数据库使用语句指定的索引列，通过遍历索引树来检索行。数据库为一个值扫描索引时，发生n次I/O 就能找到其要查找的值，其中n即B-tree索引的高度。Index Scan通常用于检索表数据，数据库以轮流方式先读取索引块，找到对应的索引键值，然后通过索引键对应的tid去读取相应的表元组。在数据量大，但是查询结果集较小的场景下，Index Scan的效率往往高于Seq Scan。
#### 典型场景
- 查询某个表中的特定行：当查询语句中包含WHERE子句时，如果WHERE子句中的条件可以通过索引列进行匹配，那么GaussDB就可能会使用Index Scan来查找符合条件的行。
- 排序：当查询语句中包含ORDER BY子句时，如果ORDER BY子句中的列可以通过索引进行排序，那么GaussDB就可能会使用Index Scan来进行排序操作。
- 聚合：当查询语句中包含GROUP BY子句时，如果GROUP BY子句中的列可以通过索引进行分组，那么GaussDB就可能会使用Index Scan来进行聚合操作。
- 连接：当查询语句中包含JOIN操作时，如果JOIN操作中的列可以通过索引进行匹配，那么GaussDB就可能会使用Index Scan来进行连接操作。
 
#### 示例
**示例1：**WHERE子句中的条件可以通过索引列进行匹配。
```
--数据准备。 
gaussdb=# CREATE TABLE test (c1 int, c2 int); 
CREATE TABLE 
gaussdb=# CREATE INDEX c1_idx ON test (c1); 
CREATE INDEX 
gaussdb=# INSERT INTO test SELECT generate_series(1, 1000000), random()::integer; 
INSERT 0 1000000
gaussdb=# INSERT INTO test SELECT generate_series(1, 1000000), random()::integer; 
INSERT 0 1000000
gaussdb=# INSERT INTO test SELECT generate_series(1, 1000000), random()::integer; 
INSERT 0 1000000
gaussdb=# EXPLAIN SELECT /*+ indexscan(test c1_idx) */ * FROM test WHERE c1 > 990000;
                              QUERY PLAN
----------------------------------------------------------------------
 [Bypass]
 Index Scan using c1_idx on test  (cost=0.00..56.78 rows=716 width=8)
   Index Cond: (c1 > 990000)
(3 rows)
```
上述示例中，Index Scan算子输出信息如下所示。
| 信息名称       | 含义                                                           |
|:---|:---|
| Index Scan | 算子的名称。                                                       |
| Index Cond | 该算子的过滤谓词，示例中的过滤条件为c1列的值大于990000。在查询执行时，满足这些条件的行会被包含在最终的结果集中。 |
   
**示例2：**ORDER BY子句中的列可以通过索引进行排序。
```
gaussdb=# EXPLAIN SELECT /*+ indexscan(test c1_idx) */ * FROM test ORDER BY c1;
                                  QUERY PLAN  
-------------------------------------------------------------------------------
 [Bypass]
 Index Scan using c1_idx on test  (cost=0.00..3815878.82 rows=2451905 width=8)
(2 rows)
```
**示例3：**GROUP BY子句中的列可以通过索引进行分组。
```
gaussdb=# EXPLAIN SELECT /*+ indexscan(test c1_idx) */ c2 FROM test WHERE c1 = 10 GROUP BY c2;
                                   QUERY PLAN
---------------------------------------------------------------------------------
 HashAggregate  (cost=31897.47..31897.49 rows=2 width=4)
   Group By Key: c2
   ->  Index Scan using c1_idx on test  (cost=0.00..31866.82 rows=12261 width=4)
         Index Cond: (c1 = 10)
(4 rows)
```
**示例4：**JOIN操作中可以通过索引进行匹配
```
gaussdb=#  EXPLAIN SELECT /*+ indexscan(t1 c1_idx) */ t1.*, t2.* FROM test t1 JOIN test t2 on t1.c1 = t2.c1;
                                      QUERY PLAN
---------------------------------------------------------------------------------------
 Hash Join  (cost=111134.00..786942.61 rows=4996829 width=16)
   Hash Cond: (t1.c1 = t2.c1), (LLVM Optimized)
   ->  Index Scan using c1_idx on test t1  (cost=0.00..146659.32 rows=3000000 width=8)
   ->  Hash  (cost=41407.00..41407.00 rows=3000000 width=8)
         ->  Seq Scan on test t2  (cost=0.00..41407.00 rows=3000000 width=8)
(5 rows)
--删除。
gaussdb=# DROP TABLE test;
```
