【问题标题】:On which columns should I create the indexes我应该在哪些列上创建索引
【发布时间】:2014-09-28 11:02:54
【问题描述】:

2 个表:

countries:
  id 
  short_name ("GE", "AR"...)
  long_name
  ....

banks:
  id
  name ("NATIONAL BANK OF COUNTRY123"...)
  country_id
  ...

鉴于我通常会进行以下类型的查找:

select * from countries c
inner join banks b
on b.country_id = c.id
where c.short_name = ? and b.name = ?

我应该在哪些列上创建索引?我想在countries 中我应该在short_name 上创建一个附加索引(id 将保留作为主要的自动增量键)。我不知道banks,如果我在name 上创建一个索引,这是一个varchar 字符串,它会高效且明智吗?

【问题讨论】:

    标签: sql database performance postgresql indexing


    【解决方案1】:

    在数字列上添加索引,如整数、数据类型的双精度...此外,在 where 子句中使用的列也可以具有索引...

    【讨论】:

    • 避免添加未使用的索引,因为它们只会减慢更新/插入的速度。多出 1 或 2 个不会使人衰弱,但如果你达到 10 或 20 个,它会非常明显,而且要准确确定哪些是必要的可能会很耗时。
    【解决方案2】:

    如果这是您的查询:

    select *
    from countries c inner join
         banks b
         on b.country_id = c.id
    where c.short_name = ? and b.name = ?;
    

    您有两种索引方法。基本思想是 SQL 引擎将从一个表中查找行(扫描),然后在另一个表中查找值。

    第一种可能是“扫描”countries,然后在banks中查找:

    countries(name, id)
    banks(country_id, short_name)
    

    第二种可能是“扫描”banks,然后在`国家中查找:

    banks(short_name, country_id)
    countries(id, name)
    

    实际上哪个更好取决于数据中值的分布。您实际上可以添加这两个集合并让 SQL 引擎决定。

    【讨论】:

    • 取国家表。我可以添加哪些索引:1) id 和 name 2) name_id (id 和 name_id) 3) id 和 id_name?
    • @Grienders 。 . . country_id, id 和/或 id, name.
    • 2 个不同的索引或 2 个列上的 1 个索引?
    • @Grienders 。 . .我的回答有什么不清楚的地方吗?适当的索引是每个表上的复合索引。
    • 是的,不清楚是“2 个不同的索引还是 2 个列上的 1 个索引?”
    【解决方案3】:

    对于short_name 上的countries 表箱索引。 (id, short_name) 等组合索引浪费资源 - 为什么:id 是主键 - 唯一,所以按第一个组件(id)查找已经给出了一行,第二个组件有什么好处?我认为short_name 也是独一无二的,所以(short_name, id) 也是如此。

    banks 表的其他情况。 country_id 在这里不是唯一的,因此您可以从索引中受益:(country_id, name)

    我认为这两个额外的索引足以满足您的查询。

    【讨论】:

    • 但银行中的“名称”可能很长,例如“刚果共和国国家银行”。你确定在上面创建索引是明智的吗?
    • name 上没有索引,但banks(country_id) 将被name 扫描,其行数与全国银行的数量一样多。如果一个国家的银行数量不多(比如 10 家),那么您可以使用索引banks(country_id)。我建议测试一下——如果这个索引的搜索速度不适合你的需要,那么创建索引banks(country_id, name)
    • 里马斯,你不明白。这是一个简单的“是-否”问题。 --- “但是银行中的“名称”可以很长,比如“刚果共和国国家银行”。你确定在上面创建索引是明智的吗?“
    • 长列索引也加快了查找速度。但是这样的索引会占用更多空间 - 所以我建议尝试使用该索引,不使用它。
    【解决方案4】:

    找出您需要哪些索引的最佳方法是测试它们。我希望您为此设置了一个开发环境,您可以加载生产数据(pg_dump 和 pg_restore)。

    如果您的表足够小,那么索引它可能根本没有帮助。例如,您的国家/地区表(假设它是国家/地区列表)可能不需要任何索引。

    如果您总是查询银行名称,并且银行表有 > 10K 条记录,那么banks(name) 索引会有所帮助。但是,如果您想获得一个国家/地区的银行列表,索引 banks(country_id) 也很好。

    如果您真的关心查询性能,请从不使用索引开始并测试每个索引以了解它带来的好处。 PostgreSQL 的解释分析工具非常出色,但使用 explain.depesz.com 会做一些额外的数学运算,让您准确计算出每个组件需要多长时间。

    【讨论】:

    • 1) 如何测试是否需要索引? 2)银行的“名称”是长度约为 30 个符号的 varchar。在上面创建索引是否明智?这不会影响性能吗?
    • 根据经验,我不会担心 varchar(30) 字段太大而无法索引 - 我从来没有遇到过任何问题。此外,除非您明确想要截断名称长度,否则我建议只使用文本。 The difference in peformence is negligible. 要测试这些东西:1) 使用 pg_dump/restore 将生产模式/数据加载到您的开发数据库中。 2) 使用 EXPLAIN ANALYZE 测试示例查询。 3) 尝试使用您认为可以加快第 2 步查询的慢速部分的索引。4) 重复第 2 步和第 3 步,直到满意为止。
    猜你喜欢
    • 2011-08-24
    • 2013-02-26
    • 1970-01-01
    • 2013-07-28
    • 2020-07-09
    • 1970-01-01
    • 2021-10-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多