乱序写入导致的索引膨胀(B-tree, GIN, GiST皆如此)

本文涉及的产品
云原生数据库 PolarDB 分布式版,标准版 2核8GB
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
RDS PostgreSQL Serverless,0.5-4RCU 50GB 3个月
推荐场景:
对影评进行热评分析
简介:

标签

PostgreSQL , 索引分裂 , 乱序写入


背景

有些场景,用户会发现重建索引,索引比原来更小。

通常这种情况是索引字段乱序写入,导致索引频繁分裂,使得索引页并不是百分百填满。膨胀使然。

B-Tree索引

由于索引页中的数据是有序的,因此在乱序写入时,索引页可能出现分裂,分裂多了,空洞就会多起来(一页里面没有填满)。

例子

1、先建索引,乱序写入。

postgres=# create table t_idx_split(id int);  
CREATE TABLE  
postgres=# create index idx_t_idx_split on t_idx_split (id);  
CREATE INDEX  
postgres=# insert into t_idx_split select random()*10000000 from generate_series(1,10000000);  
INSERT 0 10000000  
postgres=# \di+ t_idx_sp  
  
postgres=# \di+ idx_t_idx_split   
                                List of relations  
 Schema |      Name       | Type  |  Owner   |    Table    |  Size  | Description   
--------+-----------------+-------+----------+-------------+--------+-------------  
 public | idx_t_idx_split | index | postgres | t_idx_split | 280 MB |   
(1 row)  

2、先建索引,顺序写入。

postgres=# truncate t_idx_split ;  
TRUNCATE TABLE  
postgres=# \di+ idx_t_idx_split   
                                  List of relations  
 Schema |      Name       | Type  |  Owner   |    Table    |    Size    | Description   
--------+-----------------+-------+----------+-------------+------------+-------------  
 public | idx_t_idx_split | index | postgres | t_idx_split | 8192 bytes |   
(1 row)  
  
postgres=# insert into t_idx_split select generate_series(1,10000000);  
INSERT 0 10000000  
postgres=# \di+ idx_t_idx_split   
                                List of relations  
 Schema |      Name       | Type  |  Owner   |    Table    |  Size  | Description   
--------+-----------------+-------+----------+-------------+--------+-------------  
 public | idx_t_idx_split | index | postgres | t_idx_split | 214 MB |   
(1 row)  

3、先写入,后建索引。

postgres=# drop index idx_t_idx_split ;  
DROP INDEX  
postgres=# create index idx_t_idx_split on t_idx_split (id);  
CREATE INDEX  
postgres=# \di+ idx_t_idx_split   
                                List of relations  
 Schema |      Name       | Type  |  Owner   |    Table    |  Size  | Description   
--------+-----------------+-------+----------+-------------+--------+-------------  
 public | idx_t_idx_split | index | postgres | t_idx_split | 214 MB |   
(1 row)  

很显然,顺序写入时,索引大小和后建索引大小一致,没有出现膨胀。

GIN索引

GIN索引也是树结构,也有膨胀的可能。

对于gin索引,实际上膨胀现象更加的明显,因为通常GIN是对多值类型的索引,而多值类型,通常输入的顺序更加无法保证。

GIN主树索引页会膨胀较厉害。

GiST和SP-GiST索引

同样存在这个现象,当写入的空间数据BOUND BOX是空间无序写入的,那么就会导致膨胀。

重建索引,可以收缩膨胀

建议并行建索引,防止堵塞DML

使用CONCURRENTLY关键字,并行创建索引,不会堵塞DML,但是创建索引的时间比正常创建索引的时间会略长。

Command:     CREATE INDEX
Description: define a new index
Syntax:
CREATE [ UNIQUE ] INDEX [ CONCURRENTLY ] [ [ IF NOT EXISTS ] name ] ON table_name [ USING method ]
    ( { column_name | ( expression ) } [ COLLATE collation ] [ opclass ] [ ASC | DESC ] [ NULLS { FIRST | LAST } ] [, ...] )
    [ WITH ( storage_parameter = value [, ... ] ) ]
    [ TABLESPACE tablespace_name ]
    [ WHERE predicate ]
目录
相关文章
|
7月前
|
SQL 存储 关系型数据库
(五)MySQL索引应用篇:建立索引的正确姿势与使用索引的最佳指南!
在本篇中,则重点讲解索引应用相关的方式方法,例如各索引优劣分析、建立索引的原则、使用索引的指南以及索引失效与索引优化等内容。
1358 0
|
8月前
|
关系型数据库 MySQL 数据库
MySQL索引优化:深入理解索引合并
MySQL索引优化:深入理解索引合并
|
8月前
|
存储 关系型数据库 MySQL
MySQL数据库——索引(2)-B+Tree、Hash结构,索引分类(聚集索引、二级索引)
MySQL数据库——索引(2)-B+Tree、Hash结构,索引分类(聚集索引、二级索引)
115 1
|
存储 缓存 索引
PG13 B-tree索引去重
PG13 B-tree索引去重
114 0
|
存储 数据库 索引
解析B+Tree索引在H2中的实现
提到数据库索引的时候,一般都会提到 B+Tree,因为主流数据库都使用它。我们的DawnSql使用的是 H2 中的存储引擎,因此也是使用 B+Tree。这篇文章的目的是帮助读者更快的掌握 B+Tree 在存储引擎中的作用,以及具体的实现。
解析B+Tree索引在H2中的实现
|
存储 数据库 索引
B-Tree索引是干什么的?底层原理是什么?
B-Tree索引是干什么的?底层原理是什么?
160 0
|
存储 关系型数据库 索引
Hash索引和B+树索引有什么区别或者说优劣势
Hash索引和B+树索引有什么区别或者说优劣势
480 0
|
算法 关系型数据库 MySQL
mysql索引(九)索引合并
索引合并是mysql底层为我们提供的智能算法。了解索引合并的算法,有助于我们更好的创建索引。 索引合并是通过多个range类型的扫描并且合并它们的结果集来检索行的。仅合并来自单个表的索引扫描,而不是跨多个表的索引扫描。合并会产生底层扫描的三种形式:unions(合并)、intersections(交集)、unions-of-intersections(先取交集再合并)。
370 0
mysql索引(九)索引合并
|
存储 算法 关系型数据库
mysql索引(一)索引的原理
索引在MySQL中也叫做“键”或者"key"(primary key,unique key,还有一个index key),是存储引擎用于快速找到记录的一种数据结构。索引对于良好的性能非常关键,尤其是当表中的数据量越来越大时,索引对于性能的影响愈发重要,减少io次数,加速查询。 索引优化应该是对查询性能优化最有效的手段了。索引能够轻易将查询性能提高好几个数量级。 索引相当于字典的音序表,如果要查某个字,如果不使用音序表,则需要从几百页中逐页去查。
230 0
mysql索引(一)索引的原理
|
存储 NoSQL 关系型数据库
B-Tree和哈希索引比较
MySQL B-tree hash 哈希 索引 InnoDB
134 0