尽快在 Postgres 表上创建索引

mem*_*und 9 postgresql performance index configuration import

我在没有索引的 Postgres 表上有一个大型数据库导入(100GB)。

导入后,我想尽快为查询创建索引。只要索引未准备好,就不会访问表中的数据。

建立索引的最快方法是什么?我必须在 3 列(两列varchar,一列date)上建立索引。创建索引大约需要2个小时,这真的没有用。

有什么办法可以加快索引的创建吗?在数据导入之前设置索引可能不是更好,因为这会减慢导入速度?

我知道 Postgres 可以选择“不加锁”创建索引,但这不会降低性能,因为它使 Postgres 能够在创建索引时访问数据?

这是一个虚拟机。服务器的内存可以根据我的需要增加。目前我有32GB。work_mem并且maintenance_work_mem仍处于默认配置值。我没有用于数据库的 SSD。这肯定会加快速度吗?

我没有任何boolean可用于部分索引的标志或类似标志。事实上,我希望表中的每一行都被索引。

hru*_*ske 8

如果这是一个选项,您可以在数据库导入之前在外部对数据进行预排序。

在我使用 PostgreSQL 9.6.1 的测试中,一个包含三个双精度列和 10M 条随机值记录的表,在相同的数据上创建索引,但预先排序,减少了 70% 的索引创建时间:

db=# create table indexing_test_data (a varchar(50), b varchar(50), c real);       
CREATE TABLE
Time: 3,586 ms
db=# insert into indexing_test_data select random()::text, random()::text, random() from generate_series(1, 10000000);
INSERT 0 10000000
Time: 25590,475 ms
db=# select a, b, c into indexing_test_sorted from indexing_test_data order by a, b, c;
SELECT 10000000
Time: 77389,665 ms

db=# create index test_data_idx on indexing_test_data (a, b, c);
CREATE INDEX
Time: 57399,140 ms

db=# create index test_sorted_idx on indexing_test_sorted (a, b, c);
CREATE INDEX
Time: 16219,639 ms
Run Code Online (Sandbox Code Playgroud)

如果您负担得起使用具有 C 语言环境和排序规则的数据库,则可以有额外的加速,然后可以使用称为缩写键的功能,自 PostgreSQL 9.5 起可用。这将排序速度提高了 20 倍,但仅适用于 C 语言环境,因为旧库中的语言环境支持有缺陷:

db=# create database testdb lc_collate "C" lc_ctype "C" template template0;
CREATE DATABASE
Time: 429,710 ms
db=# \c testdb
You are now connected to database "testdb" as user "user".
testdb=# create table indexing_test_data (a varchar(50), b varchar(50), c real);       
CREATE TABLE
Time: 2,794 ms
testdb=# insert into indexing_test_data select random()::text, random()::text, random() from generate_series(1, 10000000);
INSERT 0 10000000
Time: 25977,964 ms
testdb=# select a, b, c into indexing_test_sorted from indexing_test_data order by a, b, c;
SELECT 10000000
Time: 20794,850 ms

testdb=# create index test_data_idx on indexing_test_data (a, b, c);
CREATE INDEX
Time: 16371,426 ms

testdb=# create index test_sorted_idx on indexing_test_sorted (a, b, c);
CREATE INDEX
Time: 8046,787 ms
Run Code Online (Sandbox Code Playgroud)

在这里,索引排序的数据大约需要 50% 的未排序时间,但与第一个版本相比,需要 57 秒,您减少了 14% 的时间

正如评论中提到的,其他事情也有帮助:maintenance_work_mem适当设置而不是运行create index concurrently(这明显变慢了)。