Performance PostgreSQL:根据所有表字段的长度创建索引
我有一个名为Performance PostgreSQL:根据所有表字段的长度创建索引,performance,postgresql,database-performance,database-indexes,Performance,Postgresql,Database Performance,Database Indexes,我有一个名为profile的表格,我想按填写最多的表格排序。每列都是JSONB列或文本列。我在很大程度上不需要这个,所以我通常会订购如下: SELECT * FROM profile ORDER BY LENGTH(CONCAT(profile.*)) DESC; 但是,这很慢,所以我想创建一个索引。但是,这不起作用: CREATE INDEX index_name ON profile (LENGTH(CONCAT(*)) 也不是 CREATE INDEX index_name ON pr
profile
的表格,我想按填写最多的表格排序。每列都是JSONB列或文本列。我在很大程度上不需要这个,所以我通常会订购如下:
SELECT * FROM profile ORDER BY LENGTH(CONCAT(profile.*)) DESC;
但是,这很慢,所以我想创建一个索引。但是,这不起作用:
CREATE INDEX index_name ON profile (LENGTH(CONCAT(*))
也不是
CREATE INDEX index_name ON profile (LENGTH(CONCAT(CAST(* AS TEXT))))
不能说我很惊讶。声明此索引的正确方法是什么?您可以声明错误标记为“不可变”的函数,并在此基础上构建索引
CREATE OR REPLACE FUNCTION len_immut(record)
RETURNS int
LANGUAGE plperl
IMMUTABLE
AS $function$
## This function lies about its immutability.
## Use it with care. It is useful for indexing
## entire table rows.
return length(join ",", values %{$_[0]});
$function$
然后
create index on profile (len_immut(profile));
SELECT * FROM profile ORDER BY len_immut(profile) DESC;
由于函数被错误地标记为不可变,如果您在表上添加或删除列,或更改列的类型,索引可能会过期。要在文本表示中测量行的大小,您可以将整行转换为文本,这比连接单个列快得多:
SELECT length(profile::text) FROM profile;
但索引中的此表达式存在3(或4)个问题:
CREATE INDEX
中不接受语法速记profile::text
,您需要在标准语法cast(profile AS text)中添加额外的括号或默认值
不可变的
函数,而将行类型强制转换为文本
不能满足此要求。您可以构建一个伪不可变的
包装函数,如Jeff所述创建索引中引用行类型,因为标识符总是首先解析为列名
文本
表示中添加列分隔符、行装饰符以及可能的转义字符。对您的用例来说应该没有多大关系pg\u column\u size()
也只是稳定的
。您可以创建一个简单而廉价的SQL包装函数:
CREATE OR REPLACE FUNCTION pg_column_size(profile)
RETURNS int LANGUAGE sql IMMUTABLE AS
'SELECT pg_catalog.pg_column_size($1)';
然后像@jjanes概述的那样继续。更多详情:
profile
为参数的函数。Postgres允许函数重载,这就是为什么我们可以使用相同的函数名。现在,当我们将匹配的行类型提供给pg\u column\u size()
时,我们的自定义函数将根据规则进行更紧密的匹配,并被选中,而不是多态系统函数。或者,使用单独的名称,并可能使函数具有多态性
相关的:
CREATE OR REPLACE FUNCTION pg_column_size(profile)
RETURNS int LANGUAGE sql IMMUTABLE AS
'SELECT pg_catalog.pg_column_size($1)';