我目前有一个具有多个属性的用户模型,我在用户表上有几个索引。
但是我正在使用偏执狂宝石,它会自动将deleted_at添加到语句中。这就是我的意思,如果我通过电子邮件搜索这是声明:
SELECT "users".* FROM "users" WHERE "users"."email" = 'test@test.com' AND ("users".deleted_at IS NULL)
我有一个关于电子邮件列的索引,这是否意味着我应该将一个deleted_at列添加到索引中以利用索引,或者它会如何正常?
答案 0 :(得分:2)
没有索引就没事了。在用户表上,电子邮件列通常是这样的,它已经非常有选择性(并且通常是唯一的),并且过滤偶尔的行也不会花费太多。
相比之下,我认为大多数用户都不会被删除,所以当你要寻找一个空值时,你的选择性会非常低。
例如,如果要按删除日期搜索用户,则deleted_at上的索引会很有用。或者所有已删除的用户。在后一种情况下,问问自己,对于需要它的偶然管理员的长查询是否值得在每行插入和更新以保持索引的额外开销。 (并不是说更新索引很慢,或者当然,但它最终会加起来。)
在这个意义上,一个更有用的索引,btw,将是deleted_at的部分索引:
create index on users (deleted_at) where (deleted_at is not null);
要使用它,请确保在where或join子句中包含where deleted_at is not null
。它通常具有非常低的基数,允许您立即查找已删除的行,而不会在更典型的数据库写入上添加微不足道的开销。
答案 1 :(得分:1)
您的查询使用当前索引来查找索引中电子邮件的值。然后,对于每个匹配记录,它将获取记录,获取已删除标志的值并可选择返回记录。
通常,电子邮件的不同记录的位置将位于不同的页面上。
使用索引中的deleted标志,它只会获取与where
子句完全匹配的数据。
因此,您的问题的答案取决于有多少记录包含NULL
与非NULL
已删除的标记。如果每个电子邮件平均有10个未删除的已删除记录,那么当前索引只需要读取一个,就会读取11个数据页。
如果在整个数据库中只删除了少数记录,那么这没有什么区别。
总的来说,在索引中添加deleted
标志可能是有益的,因为删除记录会堆积起来。