Jos*_*ith 7 postgresql indexing ruby-on-rails ruby-on-rails-4 rails-activerecord
我的UsersController#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: ?
Run Code Online (Sandbox Code Playgroud)
我相当积极,这来自以下模型验证:
validates :username, uniqueness: { case_sensitive: false }
我应该创建一个针对此快递的索引吗?如果是这样,在Rails 4中执行此操作的正确方法是什么?
mu *_*ort 13
是的,验证会进行那种查询,而那种查询将进行表扫描.
你实际上有几个问题:
您可以使用一个索引解决这两个问题.第一个问题是通过在数据库中使用唯一索引来解决的.第二个问题是通过索引结果来解决的,lower(username)
而不是username
.
AFAIK Rails仍然不理解表达式的索引,所以你必须做两件事:
从切换schema.rb
到structure.sql
保持Rails的忘记你的索引.在你的config/application.rb
想要设置:
config.active_record.schema_format = :sql
Run Code Online (Sandbox Code Playgroud)
您还必须开始使用db:structure:*
rake任务而不是db:schema:*
任务.切换到之后structure.sql
,您可以删除,db/schema.rb
因为它不会再被更新或使用; 你还想db/structure.sql
在版本控制中开始跟踪.
通过在迁移中编写一些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
Run Code Online (Sandbox Code Playgroud)当然这会让你得到PostgreSQL特有的东西,但是没什么可担心的,因为ActiveRecord无论如何都不会给你带来任何有用的可移植性.
归档时间: |
|
查看次数: |
1793 次 |
最近记录: |