两列上的唯一索引加上每列的单独索引?

时间:2009-01-31 21:02:56

标签: sql optimization indexing

我对数据库优化知之甚少,但我试图理解这种情况。

说我有下表:

cities
===========
state_id integer
name varchar(32)
slug varchar(32)

现在,我想要执行这样的查询:

SELECT * FROM cities WHERE state_id = 123 AND slug = 'some_city'
SELECT * FROM cities WHERE state_id = 123

如果我希望某个城市的“slug”在其特定状态下是唯一的,我会在state_id和slug上添加一个唯一索引。

该指数足够吗?或者我应该在state_id上​​添加另一个,以便第二个查询被优化?或者第二个查询是否自动使用唯一索引?

我正在研究PostgreSQL,但我觉得这种情况非常简单,大多数DBMS的工作方式都相似。

另外,我知道这肯定对小桌子没什么影响,但我的例子很简单。想想200k +行表。

谢谢!

4 个答案:

答案 0 :(得分:1)

[编辑:误读了这个问题...希望我的答案现在更有意义!]

在你的情况下,我建议(state_id, slug)上有1个索引。如果您只需要slug搜索,请在该列上添加索引。如果你有那些,那么在state_id上添加另一个索引是不必要的,因为第一个索引已经涵盖了它。

只要在WHERE子句中使用其列的初始段,就可以使用索引。所以例如列A,B和C上的索引将优化包含涉及A,B和C的WHERE子句的查询,仅包含A和B的WHERE子句,或仅包含A的WHERE子句。请注意,列在索引定义中出现的顺序非常important - 此示例索引不能用于仅涉及B和/或C的WHERE子句。

(当然,由查询优化器决定是否实际使用了某个特定索引,但在您拥有200k行的情况下,您可以保证state_idslug或两者都将使用其中一个指数。)

答案 1 :(得分:1)

任何体面的优化器都会看到三列的索引 - 比如说:

CREATE INDEX idx_1 ON SomeTable(Col1, Col2, Col3);

并将该索引用于以下任何条件:

WHERE Col1 = ...something...

WHERE Col1 = ...something... AND Col2 = ...otherthing...

WHERE Col3 = ....whatnot....
  AND Col1 = ...something....
  AND Col2 = ...otherthing...

也就是说,如果条件应用于索引列的任何连续前导子集,它将使用索引。虽然我使用了相等,但它也可以应用于范围(打开 - 例如大于,或者关闭(在两个值之间)。

答案 2 :(得分:1)

(state_id,slug)上的单个唯一索引就足够了。当然,当然,您需要运行EXPLAIN和/或ANALYZE(可能需要http://explain.depesz.com/之类的帮助),但最终哪些索引是否合适取决于您将成为什么类型的查询运行。请记住,索引使SELECT更快,INSERT,UPDATE和DELETE更慢,因此理想情况下只需要实际需要的索引。

此外,PostgreSQL有一个智能查询优化器:它将对小型表和大型表的查询使用截然不同的搜索计划。如果表很小,它只会执行顺序扫描,甚至不会打扰任何索引,因为使用它们的开销高于仅通过表格的强力筛选。一旦表格大小超过阈值,这将更改为不同的计划,如果表格再次变大,或者如果您更改SELECT,或者......,则可能会再次更改。

总结:您不能相信EXPLAIN和ANALYZE对数据集的结果比实际数据小得多或不同。让它工作,然后在以后快速(如果你需要)。

答案 3 :(得分:0)

要进行优化,请使用EXPLAIN http://www.postgresql.org/docs/7.4/static/sql-explain.html并亲眼看看。 但优化并不是制作这些指标的最重要原因;首先,它是一个限制数据库不合逻辑的约束。