如何确定 PostgreSQL 中索引的排序规则?

sol*_*liz 5 postgresql collation postgresql-15

在 PostgreSQL 15 中,当使用隐式排序规则创建索引时,会记录用于该索引的默认排序规则:

默认情况下,索引使用为要索引的列声明的排序规则或要索引的表达式的结果排序规则。具有非默认排序规则的索引对于涉及使用非默认排序规则的表达式的查询非常有用。

但是,在使用默认排序规则(如文档中所述)在列上创建索引后,我们可以更改列的排序规则。根据我的理解,更改列的排序规则不应更改已创建索引的排序规则。

因此,在任何时间点,我们都应该能够查询可能与相应列排序规则不同的索引的实际排序规则。

我们怎样才能做到这一点?

我做了一些测试,但并没有得出结论:

psql (15.3)
Type "help" for help.

postgres=# SELECT version();
                                   version                                    
------------------------------------------------------------------------------
 PostgreSQL 15.3 on x86_64-pc-linux-gnu, compiled by gcc (GCC) 12.2.0, 64-bit
(1 row)

postgres=# CREATE DATABASE test10
TEMPLATE = template0
LOCALE = "C"
ENCODING = 'UTF8';
CREATE DATABASE
postgres=# \c test10
You are now connected to database "test10" as user "postgres".
test10=# CREATE TABLE public.asset(
        asset_id uuid NOT NULL,
        name text NOT NULL,
        CONSTRAINT pk_asset PRIMARY KEY (asset_id)
);
CREATE TABLE
test10=# INSERT INTO public.asset VALUES
  ('100921c5-d506-4ff2-a8c4-c8250d3a2751', 'A8'),
  ('31278fae-f415-43b5-9445-4b0d8e1a7ae0', 'A9'),
  ('d8d9ff78-70d2-416c-96c8-fc40da2a9e8c', 'A10'),
  ('f0a0a526-338a-4eb6-911a-c6d077cb1e39', 'A11');
INSERT 0 4
test10=# CREATE INDEX idx_name_implicit_collation_c ON public.asset (name);
CREATE INDEX
test10=# \d public.asset
               Table "public.asset"
  Column  | Type | Collation | Nullable | Default 
----------+------+-----------+----------+---------
 asset_id | uuid |           | not null | 
 name     | text |           | not null | 
Indexes:
    "pk_asset" PRIMARY KEY, btree (asset_id)
    "idx_name_implicit_collation_c" btree (name)

test10=# SELECT indrelid::regclass::text, indexrelid::regclass::text, collname, pg_get_indexdef(indexrelid) 
FROM (SELECT indexrelid, indrelid, indcollation[i] coll FROM pg_index, generate_subscripts(indcollation, 1) g(i)) s 
  JOIN pg_collation c ON coll=c.oid
WHERE collname NOT IN ('C', 'POSIX');
 indrelid |          indexrelid           | collname |                                pg_get_indexdef                                
----------+-------------------------------+----------+-------------------------------------------------------------------------------
 asset    | idx_name_implicit_collation_c | default  | CREATE INDEX idx_name_implicit_collation_c ON public.asset USING btree (name)
(1 row)

test10=# CREATE COLLATION "natural" (provider = icu, locale = 'und-u-kn-true');
CREATE COLLATION
test10=# ALTER TABLE public.asset ALTER COLUMN name TYPE text COLLATE "natural";
ALTER TABLE
test10=# CREATE INDEX idx_name_implicit_collation_natural ON public.asset (name);
CREATE INDEX
test10=# \d public.asset
               Table "public.asset"
  Column  | Type | Collation | Nullable | Default 
----------+------+-----------+----------+---------
 asset_id | uuid |           | not null | 
 name     | text | natural   | not null | 
Indexes:
    "pk_asset" PRIMARY KEY, btree (asset_id)
    "idx_name_implicit_collation_c" btree (name)
    "idx_name_implicit_collation_natural" btree (name)

test10=# SELECT indrelid::regclass::text, indexrelid::regclass::text, collname, pg_get_indexdef(indexrelid) 
FROM (SELECT indexrelid, indrelid, indcollation[i] coll FROM pg_index, generate_subscripts(indcollation, 1) g(i)) s 
  JOIN pg_collation c ON coll=c.oid
WHERE collname NOT IN ('C', 'POSIX');
 indrelid |             indexrelid              | collname |                                   pg_get_indexdef                                   
----------+-------------------------------------+----------+-------------------------------------------------------------------------------------
 asset    | idx_name_implicit_collation_c       | natural  | CREATE INDEX idx_name_implicit_collation_c ON public.asset USING btree (name)
 asset    | idx_name_implicit_collation_natural | natural  | CREATE INDEX idx_name_implicit_collation_natural ON public.asset USING btree (name)
(2 rows)

test10=# ALTER TABLE public.asset ALTER COLUMN name TYPE text;
ALTER TABLE
test10=# \d public.asset
               Table "public.asset"
  Column  | Type | Collation | Nullable | Default 
----------+------+-----------+----------+---------
 asset_id | uuid |           | not null | 
 name     | text |           | not null | 
Indexes:
    "pk_asset" PRIMARY KEY, btree (asset_id)
    "idx_name_implicit_collation_c" btree (name)
    "idx_name_implicit_collation_natural" btree (name)

test10=# SELECT indrelid::regclass::text, indexrelid::regclass::text, collname, pg_get_indexdef(indexrelid) 
FROM (SELECT indexrelid, indrelid, indcollation[i] coll FROM pg_index, generate_subscripts(indcollation, 1) g(i)) s 
  JOIN pg_collation c ON coll=c.oid
WHERE collname NOT IN ('C', 'POSIX');
 indrelid |             indexrelid              | collname |                                   pg_get_indexdef                                   
----------+-------------------------------------+----------+-------------------------------------------------------------------------------------
 asset    | idx_name_implicit_collation_c       | default  | CREATE INDEX idx_name_implicit_collation_c ON public.asset USING btree (name)
 asset    | idx_name_implicit_collation_natural | default  | CREATE INDEX idx_name_implicit_collation_natural ON public.asset USING btree (name)
(2 rows)
Run Code Online (Sandbox Code Playgroud)

在我的测试中,以下查询

SELECT indrelid::regclass::text, indexrelid::regclass::text, collname, pg_get_indexdef(indexrelid) 
FROM (SELECT indexrelid, indrelid, indcollation[i] coll FROM pg_index, generate_subscripts(indcollation, 1) g(i)) s 
  JOIN pg_collation c ON coll=c.oid
WHERE collname NOT IN ('C', 'POSIX');
Run Code Online (Sandbox Code Playgroud)

始终返回 a,collname它是列的当前排序规则,而不是索引的预期排序规则,如下所示:

             indexrelid              | collname 
-------------------------------------+----------
 idx_name_implicit_collation_c       | default
 idx_name_implicit_collation_natural | natural
Run Code Online (Sandbox Code Playgroud)

我怀疑这是一个错误。

我们如何查询索引的实际排序规则?

Lau*_*lbe 4

当您更改列排序规则时,会重建索引:

\n
CREATE TABLE colltab (t text COLLATE "ar-EG-x-icu");\n\nCREATE INDEX collind ON colltab (t);\n\nSELECT oid, relfilenode FROM pg_class WHERE relname = 'collind';\n\n  oid  \xe2\x94\x82 relfilenode \n\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\xaa\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\n 81350 \xe2\x94\x82       81350\n(1 row)\n\nALTER TABLE colltab ALTER t TYPE text COLLATE "C";\n\nSELECT oid, relfilenode FROM pg_class WHERE relname = 'collind';\n\n  oid  \xe2\x94\x82 relfilenode \n\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\xaa\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\n 81351 \xe2\x94\x82       81351\n(1 row)\n
Run Code Online (Sandbox Code Playgroud)\n

索引后面的文件名的改变(81350 \xe2\x87\x92 81351)意味着索引被重建了。

\n