我有一张大table users(id, inserttime, ...)
,仅启用索引 id
. 我想找到在给定的 start_date
以及 finish_date
射程。 User.where(inserttime: start_date..finish_date).find_each
^这会导致搜索过程花费大量时间,因为 inserttime
列未编入索引。
我想出的解决办法是 user.id
为了 start_date
以及 finish_date
分别使用索引的 id
列。
然后这样做让所有的用户 start_id
以及 finish_id
: User.where(id: start_id..finish_id).find_each
我使用的二进制搜索函数是这样的:
def find_user_id_by_date(date)
low = User.select(:id, :inserttime).first
high = User.select(:id, :inserttime).last
low_id = low.id
high_id = high.id
low_date = low.inserttime
high_date = high.inserttime
while(low_id <= high_id)
mid_id = low_id + ((high_id - low_id) / 2);
mid = User.select(:id, :inserttime).find_by(id: mid_id)
# sometimes there can be missing users. Ex: [1,2,8,9,10,16,17,..]
while mid.nil?
mid_id = mid_id + 1
mid = User.select(:id, :inserttime).find_by(id: mid_id)
end
if (mid.inserttime < date)
low_id = mid.id + 1
elsif (mid.inserttime > date)
high_id = mid.id - 1
else
return mid.id
end
end
# when date = start_date
return (low_id < high_id) ? low_id + 1 : high_id + 1
# when date = finish_date
return (low_id < high_id) ? low_id : high_id + 1
end
我不确定我所做的是不是正确的方法来处理这个问题,甚至我的二进制搜索功能是否涵盖了所有的情况。
我认为最好的解决办法是在 inserttime
但遗憾的是,这是不可能的。
1条答案
按热度按时间f0brbegy1#
这可能不是最好的方法,但是如果id是数字的并且是连续的,您可以编写一个查询来查找介于最小和最大用户id之间的用户:
在activerecord中: