Ruby on rails 如何在Rails(使用postgres)中较低的(“用户”用户名)上创建索引
我的Ruby on rails 如何在Rails(使用postgres)中较低的(“用户”用户名)上创建索引,ruby-on-rails,postgresql,ruby-on-rails-4,indexing,rails-activerecord,Ruby On Rails,Postgresql,Ruby On Rails 4,Indexing,Rails Activerecord,我的userscoontroller#create操作中发生了顺序扫描 SELECT ? AS one FROM "users" WHERE (LOWER("users"."username") = LOWER(?) AND "users"."id" != ?) LIMIT ? Explain plan 1 Query planLimit (cost=0.00..3.35 rows=1 width=0) 2 Query plan-> Seq Scan on users (cost=0.0
userscoontroller#create
操作中发生了顺序扫描
SELECT ? AS one FROM "users" WHERE (LOWER("users"."username") = LOWER(?) AND "users"."id" != ?) LIMIT ?
Explain plan
1 Query planLimit (cost=0.00..3.35 rows=1 width=0)
2 Query plan-> Seq Scan on users (cost=0.00..3.35 rows=1 width=0)
3 Query planFilter: ?
我相当肯定,这源自以下模型验证:
验证:用户名,唯一性:{区分大小写:false}
我是否应该针对此express创建索引?如果是这样的话,在Rails 4中正确的方法是什么?是的,验证将执行这种查询,而这种查询将执行表扫描 实际上,这里有几个问题:
- 由于逻辑不在其所属的数据库中,因此验证受竞争条件的约束。数据库应负责所有数据完整性问题,而不考虑通常的Rails思想
- 您的验证会触发表扫描,没有人喜欢表扫描
lower(username)
而不是username
的结果来解决
AFAIK Rails仍然不理解表达式上的索引,因此您必须做两件事:
schema.rb
切换到structure.sql
,以防止Rails忘记索引。在config/application.rb
中,您需要设置:
config.active_record.schema_format = :sql
您还必须开始使用db:structure:*
rake任务,而不是db:schema:*
任务。一旦切换到structure.sql
,就可以删除db/schema.rb
,因为它不再被更新或使用;您还需要在修订控制中开始跟踪db/structure.sql
def up
connection.execute(%q{
create index idx_users_lower_username on users(lower(username))
})
end
def down
connection.execute(%q{
drop index idx_users_lower_username
})
end
当然,这会给您留下一些特定于PostgreSQL的东西,但这没什么好担心的,因为ActiveRecord并没有提供任何有用的可移植性。我认为这是暗示,但只是为了验证,这是否意味着我应该删除
schema.rb
?schema.rb
一旦更改了schema\u格式
,就不会用于任何事情。是的,删除它并开始跟踪修订控件中的db/structure.sql
。您的用户
表有多大?仅仅因为你有一个索引并不意味着它会被使用。查询优化器将猜测索引是否值得,猜测取决于表中数据的外观、大小。。。如果只有100个条目,那么使用索引可能比全部检查要昂贵。查询优化是一门黑色艺术,明白了。当你回答的时候,我发现上面说的正是同一件事。在开发中,是的,用户不多。所以它要做一个全表扫描。但我认为,对于更大的数据集,在生产中使用它还是更好的。@Josh Smith确保运行真空分析用户代码>创建索引后。