【问题标题】:Multi-column index order in RailsRails 中的多列索引顺序
【发布时间】:2015-08-12 15:06:45
【问题描述】:

我理解为什么索引顺序在 Rails 中很重要(来自答案 like these),例如,如果我有:

add_index :admin_users_pages, ["user_id", "page_id"]

所以我应该最快地放置“缩小行数”的字段,但我不确定这是什么意思。假设我有 2 个用户,有 2 个唯一 ID,有 300 个页面,有 300 个唯一 ID,哪个是最明智的选择?假设我有 150 个页面供第一个用户使用,150 个页面供第二个用户使用,那么索引是否类似于:

user_id page_id
1       1
1       2  
1       3

或者page_id根本不会被排序,只有索引,所以我应该得到类似的东西:

user_id page_id
1       143
1       93  
1       31

【问题讨论】:

  • 请注意,在您引用的问题中,有以下语句:“将始终查询 user_views 表以查找两列,而不是仅查找一列”。这对我来说听起来很可疑——永远不会有“查找此用户查看过的所有文章”或“查找所有查看过此文章的用户”查询?

标签: ruby-on-rails database-design indexing


【解决方案1】:

如果您要查找给定用户的页面,请使用 [:user_id, :page_id]。

如果您想为给定页面查找其用户,请使用 [:page_id, :user_id]。

如果你想两者都做,那么创建 [:user_id, :page_id] 和 [:page_id, :user_id]。

如果您有一个 user_id 和一个 page_id 并且您想找到该行(这不是很可能的情况,恕我直言),那么对于平衡树索引,您选择的顺序无关紧要。条目在第一列和第二列以及后续列的索引中排序。

在某些情况下,有争议的是应该优先选择最少的选择性(对于 Oracle 压缩的 b-tree 索引或 Oracle 跳过扫描访问),但一般来说这并不重要。

【讨论】:

  • [:user_id, :page_id] 和 [:page_id, :user_id] 是否具有相同的 b-tree 深度?
  • 我认为它没有任何实际区别,因为深度实际上是由每个节点的条目数驱动的,而不受条目顺序的影响。索引的选择应由数据的访问路径决定。
  • 这是一个只有这两个键作为列的连接表的索引。所以基本上可以有 2 个具有相同列的不同顺序的索引?
  • 是的,因为虽然它增加了修改表的开销,但每次修改只支付一次罚款。但是,每次查询数据时都会收到好处,即查询可以使用索引而无需接触表。在某些系统(例如 Oracle,通过段统计)上,读取与写入的比率是可测量的,但您可能希望读取超过写入至少一个数量级。
【解决方案2】:

在您的情况下,page_id 的选择性会更好,因为它可以极快地缩小行数(降至 2)。这意味着如果给你一个page_id,那么你可以从表中取出2条记录,然后用user_id过滤它们,但是如果你有user_id,那么你将取出150条记录并过滤它们。所以最好把'page_id'放在第一位。

【讨论】:

  • 您在这里谈论的是两种不同类型的查询——“如果给定一个 page_id,那么您可以从表中获取 2 条记录,然后按 user_id 过滤它们” i>——一种基于知道page_id,一种基于知道user_id。如果是这种情况,则应使用两个单独的索引。
  • 这与查询无关。我试图解释“缩小行”是什么意思
  • 但是您谈论必须读取表中的多少行,然后根据您是否知道 page_id 或 user_id 进行过滤——这些是不同的查询,以及必须当 page_id 和 user_id 都包含在复合索引中时,访问表以过滤掉行不适用。
  • 你说得对,这个问题更多是由查询他的数据的方式驱动的。我要解释的是,如果你首先过滤user_id,那么你有更多的树遍历和更少的叶节点搜索,这很好)
  • 如果反过来(有 300 个用户和 2 个页面)怎么办?然后创建另一个列反向工作的索引吗?这是个好主意吗?
猜你喜欢
  • 1970-01-01
  • 2010-12-22
  • 2011-05-14
  • 2011-06-14
  • 1970-01-01
  • 2011-01-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多