考虑到性能方面的改进,我想知道是否和索引是基于连接表(在Rails 3 has_and_belongs_to_many文中特别使用)有帮助。
型号和表安装
我的模型是Foo
和Bar
,每个Rails约定,我有一个连接表称为bars_foos
。 没有主键或时间戳使得该表中的老油田bar_id:integer
和foo_id:integer
。 我想知道以下哪些指标是最好的,是没有重复:
- 的化合物索引:
add_index :bars_foos, [:bar_id, :foo_id]
- 两个指标
- A.
add_index :bars_foos, :bar_id
- B.
add_index :bars_foos, :foo_id
- 两个图1和2-B的组合
基本上,我不知道,如果复合索引是足够假设它是有帮助的开始。 我相信,一个复合索引可以被用作这就是为什么我敢肯定,使用这三种线肯定会导致不必要的重复的第一个项目的单一指标。
可能的使用
最常见的用法将给予模型的实例Foo
,我会要求其关联的bars
使用的回报率语法foo.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 (?)
请纠正我的意见,如果我是不正确的,但我不相信,在Rails应用程序的情况下,这是以往任何时候都尝试做一个查询它指定既像的ID SELECT * FROM bars_foos where bar_id = ? AND foo_id = ?
SELECT * FROM bars_foos where bar_id = ? AND foo_id = ?
。
数据库
倘若有数据库特定的优化技术,我将最有可能使用PostgreSQL。 然而,其他人使用此代码可能想用它在MySQL或SQLite的取决于其Rails的配置,以便所有的答案是赞赏。
答案
人们经常重复的答案,这往往总是这样的情况往往不是就是,“看情况”。 更具体地讲,它取决于你的数据是什么,以及它如何被使用。
TL;博士解释
短TL;对于我的具体情况医生的回答(和覆盖所有未来的基地)是首选#2这就是我怀疑。 然而,选择#3会工作得很好,因为根据我的数据的使用,用于创建复合索引可以减少未来的查询查找额外的时间和空间。
充分说明
这样做的原因是,数据库自作聪明,并尝试做的事情尽可能快无论程序员的输入。 最基本的项目时要考虑添加索引是将这个对象通过此键进行查找。 如果是的话,指数有可能帮助加快这件事。 不过,该指数是否甚至被用来说来说去选择性和外地的基数。
由于外键通常是另一个AR类的ID,通常基数会很高。 但同样,这取决于你的数据。 在我的例子,如果有很多Foo
秒,但一些Bar
S,很多在我的连接表项将有simliar bar_id
秒。 随着bar_id
小号具有低基数,在索引bar_id
可能永远不会被使用,也可以顺便通过使数据库投入时间和资源*每一个新的时间加入到这个指数越来越bars_foos
项创建。 这同样有许多Bar
S和几个Foo
S和几两的。
一般的经验是,考虑在表上的索引时,决定是否参赛作品将被同时望向了这个领域,如果这个领域具有较高的基数。 也就是说,它这个领域有许多独特的价值? 在大多数的情况下连接表“这取决于”我们必须更仔细地想想该数据表示和关系本身。 就我而言,我将同时拥有许多Foo
S和Bar
S和将查找Foo
通过其相连的S bar
S和反之亦然。
另外一个很好的答案,我在办公室得到的是,“为什么你担心你的索引?建立你的应用程序!”
脚注
*在类似的问题上STI指数有人指出,索引的成本是非常低的,所以当有疑问,只需添加它。
取决于你如何去查询数据。
假设你要搜索所有这些...
-
WHERE bar_id = ?
-
WHERE foo_id = ?
-
WHERE bar_id = ? AND foo_id = ?
......那么你或许应该对指数走{bar_id, foo_id}
和索引{foo_id}
。
虽然你也可以创建第三个指数{bar_id}
,维护额外的指数的价格可能会超过更好的效益聚集在小的索引。
还有,你怎么打算支付使用索引的查询? 一些替代品,如...
-
{foo_id, bar_id}
和{bar_id}
-
{foo_id, bar_id}
和{bar_id, foo_id}
...可能包括某些类型的查询更好的。
覆盖是一个平衡的行为 - 有时加入索引的字段只用于覆盖的目的是有道理的,有时不是。 你不会知道,直到你衡量现实的数据。
(免责声明:我不熟悉的红宝石这个答案纯粹是从数据库的观点。)