如果我有一张大表:
varchar foo
integer foo_id
integer other_id
varchar other_field
我可能正在进行如下查询:
select * from table where other_id=x
显然我需要在other_id上使用索引来避免表扫描。
如果我也在这样做:
select * from table where other_id=x and other_field='y'
我是否希望在other_field上使用其他索引,或者如果我从未这样做,那就是浪费:
select * from table where other_field='y'
即。我只在查询中将other_field与other_id一起使用。
[other_id,other_field]的复合索引会更好吗?或者这会导致第一次简单查询的表扫描?
答案 0 :(得分:2)
如果您还没有使用这两个,请使用EXPLAIN
and EXPLAIN ANALYZE
。一旦了解了查询计划基础知识,您就能够非常有效地优化数据库查询。
现在回答这个问题 - 在不了解价值观的情况下说些什么可能会产生误导。如果任何特定other_field
没有那么多other_id
个值,那么简单的索引other_id
就足够了。如果有很多other_field
个值(即数千个),我会考虑制作复合索引。
我是否希望在other_field上使用其他索引,或者如果我从未这样做,那就是浪费:
是的,这很可能浪费空间。 Postgres是able to combine two indexes,但条件必须恰到好处。
[other_id,other_field]的复合索引会更好吗?
可能会。
或者是否会导致第一次简单查询的表扫描?
Postgres只能为第一列使用多列索引(不完全正确 - 检查答案评论)。
基本规则是 - 获取真实数据集,准备要优化的查询。对这些查询运行EXPLAIN ANALYZE
。尝试重写它们(即连接而不是子选择,反之亦然)并检查性能(EXPLAIN ANALYZE
)。尝试添加您认为可能有帮助的索引并检查性能(EXPLAIN ANALYZE
)...如果没有帮助,请不要忘记丢弃不必要的索引。
如果您仍然遇到问题且数据集很大(数千万+),您可能需要重新考虑甚至运行特定查询。可能需要不同的方法(例如批处理/异步处理)或特定任务的不同技术。
答案 1 :(得分:0)
如果other_id
具有高度选择性,那么您可能根本不需要other_field
上的索引。如果索引中只有少数几行匹配other_id=x
,那么查看每一行以查看它们是否也匹配other_field=y
可能足够快,不会打扰更多索引。
如果事实证明您确实需要更快地进行查询,那么您几乎肯定需要复合索引。 other_field
上的独立索引不太可能有所帮助。
答案 2 :(得分:0)
接受的答案并不完全准确 - 如果您需要在问题中提到的所有三个查询,那么您实际上需要两个索引。
让我们看看哪些索引满足查询中的哪个WHERE子句:
{other_id} {other_id, other_field} {other_field, other_id} {other_field}
other_id=x yes yes no no
other_id=x and other_field='y' partially yes yes partially
other_field='y' no no yes yes
因此,为了满足所有3个WHERE条款,您需要:
根据您的数据分布情况,您也可以使用{other_id}和{other_field},但在选择该解决方案之前,您应该仔细衡量。此外,您可以考虑将*
替换为较窄的字段集,然后将covering替换为索引,但这是另一个主题......
1 " Fatter"解决方案比其他两个 - 只考虑您是否有特定的覆盖需求。