我的网站上有一个多表搜索工具,用分页显示结果。
PostgreSQL表有几万行,我想提高性能:如果我搜索一个单词(或几个),它需要几秒钟,但如果我搜索一个字母(对于例子" e"),大约需要20秒。
这是一个非常简化的数据库,用于示例目的:
create table DOG
(
id_dog SERIAL PRIMARY KEY,
name VARCHAR(100) UNIQUE NOT NULL,
birth_date TIMESTAMP NULL
);
create table CAT
(
id_cat SERIAL PRIMARY KEY,
name VARCHAR(100) UNIQUE NOT NULL,
birth_date TIMESTAMP NULL
);
create table BIRD
(
id_bird SERIAL PRIMARY KEY,
name VARCHAR(100) UNIQUE NOT NULL,
birth_date TIMESTAMP NULL
);
insert into DOG values (0, 'Rex', '2002-03-05 12:02:06');
insert into DOG values (1, 'Rantanplan', '2002-03-05 12:02:06');
insert into DOG values (2, 'Milou', '2002-03-05 12:02:06');
insert into CAT values (0, 'Grominet', '2002-03-05 12:02:06');
insert into CAT values (1, 'Bella', '2002-03-05 12:02:06');
insert into CAT values (2, 'Molly', '2002-03-05 12:02:06');
insert into BIRD values (0, 'Titi', '2002-03-05 12:02:06');
insert into BIRD values (1, 'Bip-Bip', '2002-03-05 12:02:06');
insert into BIRD values (2, 'Sunny', '2002-03-05 12:02:06');
这是相应的简化请求(在实际情况下,我在更多字段中搜索,表格不相似):
select *, count(*) over() as count
from
(
(
select id_dog as id, birth_date as date, name as title, varchar(4) 'DOG' as table
from DOG d
where unaccent(lower(array_to_string(array[d.name, to_char(d.birth_date, 'YYYY-MM-DD HH24:MI:SS')], ' ')))
like '%' || lower(unaccent('a')) || '%'
)
union
(
select id_cat as id, birth_date as date, name as title, varchar(4) 'CAT' as table
from CAT c
where unaccent(lower(array_to_string(array[c.name, to_char(c.birth_date, 'YYYY-MM-DD HH24:MI:SS')], ' ')))
like '%' || lower(unaccent('a')) || '%'
)
union
(
select id_bird as id, birth_date as date, name as title, varchar(4) 'BIRD' as table
from BIRD b
where unaccent(lower(array_to_string(array[b.name, to_char(b.birth_date, 'YYYY-MM-DD HH24:MI:SS')], ' ')))
like '%' || lower(unaccent('a')) || '%'
)
)
as results order by DATE offset 0 limit 10;
有什么想法改善这个吗?也许有左联?
问题似乎是我需要计算结果的数量才能显示我的分页。如果我限制每个子选择中的结果数量,则查询运行速度很快,但我没有得到正确的结果计数。