优化多个左连接表以在多列上使用偏移量、限制和分页计数进行全文搜索

optimisation of multiple left joined tables for fulltextsearch over multiple columns with offset, limit and count for pagination

我目前有四个 table 需要使用左连接进行连接。 大约有400_000(40万)条数据记录(以后还会增加)。

除了left join之外,还必须能够高效执行以下操作:

我自己有几个想法来优化这个需求。

全文搜索:

偏移,极限:

计数

可以添加列或 table 来提供帮助。 只要保留所有数据,也可以更改结构。

如果postgres没有所需的功能,也可以更换数据库系统。

tables:

CREATE TABLE company_codes (
    id int2 NOT NULL,
    name varchar(20) NOT NULL,
    CONSTRAINT company_codes_pk PRIMARY KEY (id)
);

CREATE TABLE purchasing_mandant_names (
    id int2 NOT NULL,
    "name" varchar(50) NOT NULL,
    CONSTRAINT archiving_coding_keys_pkey PRIMARY KEY (id),
    CONSTRAINT purchasing_mandant_names_un UNIQUE (name)
);

CREATE TABLE purchasing (
    id int4 NOT NULL GENERATED BY DEFAULT AS IDENTITY,
    mandant_id int2 NOT NULL,
    company_code int4 NOT NULL,
    sequence_number int8 NOT NULL,
    "year" int2 NOT NULL,
    "month" int2 NOT NULL,
    CONSTRAINT purchasing_check_month CHECK (((month >= 1) AND (month <= 12))),
    CONSTRAINT purchasing_check_year CHECK (((year >= 2000) AND (year <= 2100))),
    CONSTRAINT purchasing_client_plant_sequence_number_key UNIQUE (mandant_id, company_code, sequence_number),
    CONSTRAINT purchasing_pkey PRIMARY KEY (id)
);

ALTER TABLE purchasing ADD CONSTRAINT purchasing_company_code_fk FOREIGN KEY (company_code) REFERENCES company_codes(id);
ALTER TABLE purchasing ADD CONSTRAINT purchasing_mandant_id_fkey FOREIGN KEY (mandant_id) REFERENCES purchasing_mandant_names(id) NOT VALID;

CREATE TABLE purchasing_pages (
    purchasing_id int8 NOT NULL,
    page_path varchar(255) NOT NULL,
    CONSTRAINT purchasing_pages_check_page_path CHECK (((page_path)::text ~ '^([a-zA-Z0-9\-_ ]+\/)+[a-zA-Z0-9\-_ ~]+\.[tT][iI][fF]'::text)),
    CONSTRAINT purchasing_pages_purchasing_id_page_path_key UNIQUE (purchasing_id, page_path)
);
ALTER TABLE purchasing_pages ADD CONSTRAINT purchasing_pages_id_fkey FOREIGN KEY (purchasing_id) REFERENCES purchasing(id) ON UPDATE CASCADE ON DELETE RESTRICT;

当前慢速搜索

SELECT p.id,
    p.mandant_id AS mandant_code,
    pmn.name AS mandant_name,
    p.company_code,
    cc.name AS company_name,
    p.sequence_number,
    p.year,
    p.month,
    pp.page_path
   FROM purchasing p
     LEFT JOIN purchasing_pages pp ON p.id = pp.purchasing_id
     LEFT JOIN purchasing_mandant_names pmn ON p.mandant_id = pmn.id
     LEFT JOIN company_codes cc ON p.company_code = cc.id
       where p.mandant_id::text like '%32%'
        or pmn.name::text like '%32%'
        or p.company_code::text like '%32%'
        or cc.name::text like '%32%'
        or p.sequence_number::text like '%32%'
        or p.year::text like '%32%'
        or p.month::text like '%32%'
     order by p.id desc
     offset 10 fetch first 10 rows only

我的解决方法: (我认为会有更好的选择,但这些是我自己找到的唯一选择)

全文搜索:

我为每一列创建了一个 gin_trgm_ops。 我也对 wildspeed 感兴趣。不幸的是,不再支持此扩展。 wildspeed 也有使用更短长度 < 3 的优势。 可能以后会再往这个方向看,看看有没有类似的扩展。

偏移,限制:

遗憾的是,应用过滤器时没有优化选项。 为了优化性能,我在应用程序本身中构建了几个选项。 如果直接link到一个页面,offset,limit一定要用,因为没有别的可能。 除了这种可能性之外,现在还有一个偏移量 - 先前的偏移量和最后一个 id。这样,索引至少用于进一步导航。 但只是直接跳转没有optimnierungsmöglichkeiten,因为数据也被过滤了。

计数

我直接用一个count(*) OVER()结合偏移量限制搜索过滤器,所以只需要执行一个查询。这是我为此找到的唯一优化。