考虑到性能的提高,我想知道在连接表(专门用于Rails 3 has_和_belient_to_many上下文)上是否以及哪些索引是有用的.

模型和表格设置

我的型号是FooBar,按照rails惯例,我有一个名为bars_foos的联接表.表bar_id:integerfoo_id:integer中的旧字段没有主键或时间戳.我想知道以下哪项指标是最好的,并且没有重复:

  1. A复合指数:add_index :bars_foos, [:bar_id, :foo_id]
    • 两个索引
    • A.add_index :bars_foos, :bar_id
    • B.add_index :bars_foos, :foo_id
  2. 1和2-B的组合

基本上,我不确定复合指数是否足够,假设它从一开始就有帮助.我相信复合索引可以用作第一项的单一索引,这就是为什么我pretty%确信使用所有三行肯定会导致不必要的重复.

可能的用法

最常见的用法是给出Foo型的一个实例,我将使用foo.bars的RoR语法询问其关联的bars,反之亦然,bar.foos将给出Bar型的一个实例.

这些将分别生成SELECT * FROM bars_foos WHERE foo_id = ?SELECT * FROM bars_foos WHERE bar_id = ?类型的查询,然后使用这些生成的ID生成SELECT * FROM bars WHERE ID in (?)SELECT * FROM foos WHERE ID in (?).

如果我不正确,请在 comments 中纠正我,但我不相信,在Rails应用程序的上下文中,它会try 在指定两个ID(如SELECT * FROM bars_foos where bar_id = ? AND foo_id = ?)的情况下执行查询.

数据库

如果有特定于数据库的优化技术,我很可能会使用PostgreSQL.然而,其他使用这段代码的人可能希望在MySQL或SQLite中使用它,这取决于他们的Rails配置,所以所有答案都很感谢.

推荐答案

The Answer

经常被重复的答案往往是"视情况而定",而事实往往总是如此更具体地说,这取决于你的数据是什么以及如何使用.

tl;dr Explanation

短tl;我的具体病例(以及future 所有病例)的答案是choice #2,这是我所怀疑的.然而,选项#3可以很好地工作,因为根据我对数据的使用情况,创建复合索引所用的额外时间和空间可能会减少future 的查询查找.

The Full Explanation

这是因为数据库试图变得智能化,并尽可能快地完成任务,而不考虑程序员的输入.在添加索引时要考虑的最基本的项目是这个对象将被这个键查找.如果是,索引可能有助于加快速度.然而,这个指数是否被使用,都取决于字段的 Select 性和基数.

由于外键通常是另一个AR类的ID,所以基数通常很高.但同样,这取决于你的数据.在我的示例中,如果Foo多而Bar少,那么我的联接表中的许多条目都会有simliar bar_id.由于bar_id的基数较低,bar_id上的索引可能永远不会被使用,并且可能会因为每次创建新的bars_foos条目时,数据库都会花费时间和资源*来添加到该索引而受到阻碍.同样的道理也适用于很多Bar和很少的Foo,而且两者都很少.

一般的经验是,在考虑表上的索引时,请确定该字段是否同时查找条目,以及该字段是否具有较高的基数.也就是说,这个字段有很多不同的值吗?在大多数联接表的情况下,"这取决于",我们必须更仔细地考虑数据代表什么以及关系本身.在我的例子中,我将有both多个FooBar,并将通过它们关联的bar查找Foo,反之亦然.

我在办公室得到的另一个好答案是:"你为什么担心你的索引?构建你的应用程序!"

脚注

*在一个类似的问题on indexes on STI中,有人指出,指数的成本非常低,所以当有疑问时,只需添加它即可.

Ruby-on-rails相关问答推荐

使用turbo流的部分渲染在rails 7中不起作用.

使用has_many_through关联创建记录 – Ruby on Rails

使用嵌套属性时如何自动将父 ID 分配为外键?

如何从 New Relic 交易中获取 TraceId?

无效的单表继承类型:Rails

Ruby Sinatra Web 服务在 localhost:4567 上运行,但不在 IP 上

如何在 YAML 中声明带有单引号和双引号的字符串?

如何获取 Ruby on Rails 生成的表单元素 id 以供 JavaScript 参考?

跳过模型中的某些验证方法

rails:防止闪烁消息显示两次

没有要加载的文件 - readline

是否可以在 Rails 中否定范围?

Rails:参数太少

是否有与 PHP 的 isset() 等效的 Rails?

如何按值按降序对哈希进行排序并在 ruby​​ 中输出哈希?

Rails:进行不可逆转的迁移是不是很糟糕?

如何测试自定义验证器?

Ruby:如何将一种方法接收到的所有参数和块传递给另一种方法?

在 Rails 4.1 中,如何通过枚举符号查找记录?

为什么 Mac OS X 带有 ruby​​/rails?