【问题标题】:PostgreSQL - Alter Column used for a Fulltext Generated ColumnPostgreSQL - 用于全文生成列的更改列
【发布时间】:2022-05-03 02:13:29
【问题描述】:

在 PostgreSQL 13 上,我有一个这样定义的表:

create table my_table (
   id serial8 primary key,
   title varchar(50),
   description varchar(512),
   french_vector_text tsvector generated always as (to_tsvector('french', coalesce(title, '') || ' ' || coalesce(description, ''))) stored
);

create index IDX_FULL_TEXT on my_table using GIN(french_vector_text);

它工作正常。但是,当我尝试更改用于生成向量的列时,像这样

alter table my_table
alter column title type varchar(100);

我收到一条错误消息,告诉我无法更改用于计算另一列的列,这是公平的。我通过删除带有索引的向量列,更改标题列,然后重新创建列和索引来使其工作。

alter table my_table
drop column french_vector_text;

alter table my_table
alter column title
type varchar(100);

alter table my_table
add column french_vector_text tsvector generated always as (to_tsvector('french', coalesce(title, '') || ' ' || coalesce(description, ''))) stored;

create index IDX_FULL_TEXT on my_table using GIN(french_vector_text);

再次运行良好,但实际上,该列是 7 列的聚合,其中一些具有相当大的文本,并且该表可能包含几万条记录。所以操作需要一些时间才能完成。

即使更改架构不是日常操作,我想知道是否有更有效的解决方案不需要删除列并完全重新创建索引。

我想过一个触发器,但我宁愿保留生成的列。所以我尝试创建一个IMMUTABLE 函数:

create function my_french_vector(text_to_transform varchar) returns tsvector as $$ 
BEGIN   
    return to_tsvector('french', text_to_transform);
end 
$$ LANGUAGE plpgsql
immutable;

并使用它来代替普通的to_tsvector。但显然,它也不起作用,因为该列仍然被引用。

至于我的问题,有没有办法改变生成值中使用的列,而不必删除它并在之后重新创建整个内容?

【问题讨论】:

    标签: postgresql


    【解决方案1】:

    我根本不会使用生成的列,而是在表达式上定义索引:

    CREATE INDEX french_text_idx ON my_table
       (to_tsvector('french', coalesce(title, '') || ' ' || coalesce(description, '')));
    

    然后将查询修改为

    ... WHERE to_tsvector('french', coalesce(title, '') || ' ' || coalesce(description, ''))
                 @@ to_tsquery('french', 'whatever')
    

    它会使用索引。

    添加新列时,创建一个包含新列的新索引 (CONCURRENTLY),然后更改应用程序中的查询,然后删除旧索引。

    如果您不想更改应用程序中的查询,请在包含带有索引表达式的计算列的表上定义一个视图,那么您所要做的就是CREATE OR REPLACE 视图。

    【讨论】:

    • 我没有考虑视图,我会研究一下,谢谢。只是一个问题,我最初使用了一个生成的列,因为我读到there 他们更快,因为在请求时调用to_tsvector 没有开销。视图+索引不会更慢吗?
    • 这取决于你有多少搜索结果以及 PostgreSQL 选择的索引扫描类型:如果它必须“重新检查”很多行,它可能会稍微慢一些。另一方面,存储列也需要在INSERT 上计算,它占用空间。你可以测试,但我认为性能差异不会很大。
    猜你喜欢
    • 1970-01-01
    • 2013-03-31
    • 2012-08-11
    • 2017-10-21
    • 1970-01-01
    • 2013-10-16
    • 1970-01-01
    • 2016-08-25
    • 1970-01-01
    相关资源
    最近更新 更多