如何衡量数据库索引的成本?

Dan*_*oak 9 sql database postgresql indexing

是否有一种很好的方法来判断在Postgres中创建数据库索引的成本(更慢INSERTS,构建索引的时间,重新索引的时间)是否值得获得性能提升(更快SELECTS)?

Chr*_*ers 5

我实际上不同意Hexist.PostgreSQL的规划器非常好,它支持基于物理顺序扫描对表文件的良好顺序访问,因此索引不一定有用.此外,在许多情况下,计划者必须选择一个索引.此外,您已经为唯一约束和主键创建主键.

我认为PostgreSQL的一个很好的默认位置(MySQL btw完全不同!)是等到你需要一个索引来添加一个,然后只添加你最需要的索引.然而,这仅仅是一个起点,它假设缺乏查看查询计划的普遍缺乏经验或缺乏对应用程序可能去向的理解.在这些领域有经验很重要.

通常,如果您的表可能跨越10页以上(即40kb的数据和标题),那么外键是个好主意.可以明确地假设这些.跨越1页的小查找表永远不应该具有非唯一索引,因为这些索引永远不会用于选择(没有查询计划胜过单页的顺序扫描).

除此之外,您还需要查看数据分布.索引布尔列通常是一个坏主意,并且有更好的方法来索引与布尔搜索相关的事物(部分索引是一个很好的例子).类似地,索引常用函数输出有时似乎是一个好主意,但情况并非总是如此.考虑:

CREATE INDEX gj_transdate_year_idx ON general_journal (extract('YEAR' FROM transdate));
Run Code Online (Sandbox Code Playgroud)

这不会做太多.但是,如果通过递归CTE与稀疏索引扫描配对,则transdate索引可能很有用.

一旦基本索引到位,那么问题就变成了你需要添加的其他索引.这通常最好留待以后使用案例审查,而不是最初设计的.人们发现性能显着受益于PostgreSQL上的索引更少,这种情况并不少见.

另一个需要考虑的重要事项是您创建的索引类型,这些索引通常是特定于用例的.例如,如果常规对域很重要,并且如果您经常基于初始元素进行搜索,那么数组记录上的b树索引可能有意义,但如果常规不重要,我会建议使用GIN索引,因为btree会做得很少(当然这是一个原子红旗,但有时候在Pg中有意义).即使常规很重要,有时你也需要GIN索引,因为你需要能够进行交换式扫描,就好像不是普通性一样.如果使用ip4r存储cidr块并使用EXCLUDE约束来确保没有任何块包含任何其他块(实际扫描需要使用重叠运算符而不是包含运算符,因为您不知道哪一侧是操作员违规将被发现).

同样,这有点特定于数据库.例如,在MySQL上,Hexist的建议是正确的.但是在PostgreSQL上,注意问题是件好事.

就测量而言,最好的工具是 EXPLAIN ANALYZE


hex*_*ist 4

一般来说,除非您有一个日志或存档表,您不会非常频繁地执行选择(或者如果它们需要一段时间才能运行也没关系),否则您应该对您的 select/update/deelete 语句将在 where 中使用的任何内容建立索引条款。

然而,这并不总是像看起来那么简单,因为仅仅因为列在 where 子句中使用并被索引,并不意味着 sql 引擎将能够使用索引。使用postgresql 的EXPLAINEXPLAIN ANALYZE功能,您可以检查选择中使用了哪些索引,并帮助您确定在列上建立索引是否会对您有所帮助。

这通常是正确的,因为如果没有索引,您的选择速度会从一些 O(log n) 查找操作下降到 O(n),而您的插入速度只会从 cO(log n) 提高到 dO(log n),其中 d 是通常小于 c,即您可以通过没有索引来加快插入速度,但是如果它们没有索引,您将降低选择速度,因此在数据上建立索引几乎总是值得的如果你要选择反对它。

现在,如果您有一些小表,您对其进行大量插入和更新,并经常删除所有条目,并且仅定期执行一些选择,那么没有任何索引可能会更快。但是,这会这是一个相当特殊的案例场景,因此您必须进行一些基准测试并确定它在您的特定案例中是否有意义。