我正在PostgreSQL中设计一个数据库的模式,该模式将包含像Stack Overflow这样带有标签的帖子。用户可以通过不同的标签搜索最近的帖子。从我的研究中,我发现通过标签搜索将受益于在标签列上使用广义反向索引。以下是表格的相关列:
+--------+---------------------------+----------+
| p_id | time | tags |
+--------+---------------------------+------- --+
| 001 | 2020-04-30T23:35:50+00:00 | [CA,CD] |
| 109 | 2020-03-30T23:34:50+00:00 | [AB] |
| 321 | 2019-10-30T23:34:50+00:00 | [CD,AB] |
+--------+---------------------------+----------+
然而,为了显示50条最新的帖子,数据库需要扫描与给定标签匹配的所有行。这可能是有问题的,因为在现实世界中,只有少数标签最终变得流行,而大部分文档通常包含少数标签。因此,大多数用户最终会查询大部分数据,从而使标签上的GIN无效。我还认为索引时间不会有用,因为GIN在标记上选择的行会按时返回一个未排序的列表。
有没有一种方法可以构建一个既可以利用时间标签又可以利用标签的指数,或者这是一种无法改进的权衡?
编辑:
我没有对它进行基准测试,因为我做这个练习是为了学习sql。然而,这是我想要运行的预期查询。
Select p_id
From Table
Where tags @> ?
And
time between ? and ?
基准测试不是学习SQL,而是学习性能。并且您提出的查询与您的描述不匹配,因为";50最近的";应该具有ORDER BY…DESC和LIMIT 50,而不是在WHERE子句中具有时间上的BETWEEN条件。
如果标签上有GIN索引,时间上有常规索引,那么它将有两种选择。如果您的标记非常有选择性,它会使用GIN索引提取所有已标记的条目,然后对少量行进行排序。对少量行进行排序很快。如果标签非常受欢迎,它将遍历时间索引,一旦达到极限就停止。如果有合理的统计数据,它应该做出合理明智的决定,决定哪一个会更快。