为公寓网站构建搜索引擎,我不知道如何索引apartments
表。
查询示例:
...WHERE city_id = 1 AND size > 500 AND rooms = 2
...WHERE area_id = 2 AND ad_type = 'agent' AND price BETWEEN 10000 AND 14000
...WHERE area_id = 2 OR area_id = 4 AND published_at > '2016-01-01' AND ad_type = 1
正如您所看到的,列可能会有很大差异,WHERE子句中的列数最多可以为10,甚至可能更多。
答案 0 :(得分:6)
您必须弄清楚您将在此查询中使用的WHERE
条款,每个条款的发生频率以及每种条件的选择性。
除非必须,否则不要为很少发生的查询编制索引。
使用多列索引,从=
比较中出现的列开始。
关于多列索引中列的顺序,请从将在查询中使用的那些列开始(索引可用于仅包含其某些列的查询,前提是它们位于索引的开头)。
您可能会忽略选择性较低的列,例如gender
。
例如,对于您的上述查询,如果它们都是频繁的并且所有列都是选择性的,那么这些索引就会很好:
... ON apartments (city_id, rooms, size)
... ON apartments (area_id, ad_type, price)
... ON apartments (area_id, ad_type, published_at)
这些索引也可以用于WHERE
子句,其中只包含area_id
或city_id
。
索引太多是不好的。
如果上述方法会导致索引太多,例如因为用户可以为WHERE
子句选择任意列,所以最好对单个列进行索引,或者偶尔对经常组合在一起的列进行索引。
这样PostgreSQL可以选择位图索引扫描来组合一个查询的多个索引。这比常规索引扫描效率低,但通常优于顺序扫描。
答案 1 :(得分:1)
Postgres 9.6 提供了一个新的扩展程序,以准确地解决您的难题:
从将三元组索引或文本搜索带到Postgres的同一作者(以及其他内容)。
所有相关列上的单个 bloom索引适用于WHERE
子句中任何组合 - 即使不是单独的btree每列的索引。但是,与许多索引相比,单个索引 更小且维护成本更低。你必须权衡成本和收益。
bloom索引擅长许多索引列,可以通过多种方式进行组合。
我可能将bloom索引作为“catch-all”与一些定制的多列btree索引相结合,以优化最常见的组合(along the guidelines provided by @Laurenz)和最常查询列上的一些单列索引。
更多解释:
该功能是新功能,有一些重要限制。引用手册:
模块中仅包含
int4
和text
的运算符类。搜索仅支持
=
运算符。但是可以添加对具有并集和交集操作的数组的支持 将来
所以不适用于published_at
,它看起来像date
(但你仍然可以提取EPOCH和索引),而且只适用于等式谓词。
创建扩展后(每个数据库一次):
CREATE EXTENSION bloom;
创建bloom索引:
CREATE INDEX tbl_bloomidx
ON tbl USING bloom (area_id, city_id, size, rooms, ad_type); -- many more columns?
还有其他人:
CREATE INDEX tbl_published_at ON tbl (published_at);
CREATE INDEX tbl_published_at ON tbl (price);
-- some popular combinations...
The manual有一些比较bloom,multicolumn和single-column btree索引的例子。非常有见地。