我使用Rails 5和Postgres。我有一个表名buckets
,没有列被索引。在我的本地机器上,我创建了55,000个虚拟记录。我只需要获取一条记录,其中bucket_type等于PR且issued_date为nil(有7种不同的bucket_type,如PR,CA,US,EU,VN,BU和GY),所以我尝试了2个不同的查询,其中{ {1}}和一个.first
,以查看哪一个表现得更快。
.last
此查询需要大约1.5毫秒
Bucket.where({issued_date: nil, bucket_type: 'PR'}).first
此查询大约需要6.5毫秒
然而,在生产(Heroku)时,在桶表中有210万条记录,结果却相反:
Bucket.where({issued_date: nil, bucket_type: 'PR'}).last
此查询大约需要750毫秒
Bucket.where({issued_date: nil, bucket_type: 'PR'}).first
此查询大约需要150毫秒
我有两个问题:
Bucket.where({issued_date: nil, bucket_type: 'PR'}).last
条款之后.first
和.last
的效果在本地与制作上有所不同?where
或{{1}添加任何索引 }或两列?答案 0 :(得分:2)
我真的不能告诉你第一个问题的回答,但对于第二个问题,
好吧,你应该使用limit
。
让我们看看差异:
User.where(is_disabled: 0).first
# Oracle
SELECT * FROM (
SELECT "USERS".* FROM "USERS" WHERE "USERS"."IS_DISABLED" = :a1
ORDER BY "USERS"."ID" ASC
) WHERE ROWNUM <= :a2
# MariaDB
SELECT `users`.* FROM `users` WHERE `users`.`is_disabled` = 0
ORDER BY `users`.`id` ASC LIMIT 1
你首先在oracle中看到所有用户都被选中,然后查询被包装到只选择第一个。这当然很糟糕,MySQL / MariaDB没有做到这一点。但是按user_id排序(井轨不是MariaDB)
User.where(is_disabled: 0).limit(1)
# Oracle
SELECT "USERS".* FROM "USERS" WHERE "USERS"."IS_DISABLED" = :a1
AND ROWNUM <= :a2
#MariaDB
SELECT `users`.* FROM `users` WHERE `users`.`is_disabled` = 1 LIMIT 1
在Oracle中,只有一个用户从一开始就被选中,这更快。 MariaDB不会对用户进行排序也会更快。
P.S。这可能会根据使用的数据库而改变,但无论如何都要limit
。但只要我们不知道使用过的数据库,你的问题1就无法解决。此外,这应该分为两个问题