Sql 如何从我的RubyonRails应用程序中解决这种方法的高响应时间问题

Sql 如何从我的RubyonRails应用程序中解决这种方法的高响应时间问题,sql,ruby-on-rails,json,ruby,activerecord,Sql,Ruby On Rails,Json,Ruby,Activerecord,我的Rails API中有这种方法,它不断向我发送高响应时间警报。根据我目前的知识,我已经尽可能地优化了它,但它显然仍然不起作用 对于如何优化这些查询的任何帮助,我们将不胜感激: 这是我获取标记并将其发送到API的方法 首先我去拿地址 longitude = params[:longitude] latitude = params[:latitude] @addresses = Address.joins('INNER JOIN users ON users.id = addres

我的Rails API中有这种方法,它不断向我发送高响应时间警报。根据我目前的知识,我已经尽可能地优化了它,但它显然仍然不起作用

对于如何优化这些查询的任何帮助,我们将不胜感激:

这是我获取标记并将其发送到API的方法

首先我去拿地址

  longitude = params[:longitude]
  latitude = params[:latitude]

  @addresses = Address.joins('INNER JOIN users ON users.id = addresses.addressable_id')
                      .joins('INNER JOIN items ON items.user_id = users.id')
                      .where('items.name IS NOT NULL').where("items.name <> ''")
                      .where('items.visibility = TRUE')
                      .where('items.photo IS NOT NULL').where("items.photo <> ''")
                      .where('addresses.latitude IS NOT NULL AND addresses.addressable_type = ? ', "User")
                      .near([latitude, longitude], (params[:distance].to_i + 1000))
经度=参数[:经度] 纬度=参数[:纬度] @addresses=Address.joins('users.id=addresses.addressable\u id'上的内部联接用户) .joins('items.user\u id=users.id'上的内部联接项) .where('items.name不为NULL')。where('items.name')) .where('items.visibility=TRUE') .where('items.photo不为NULL')。where('items.photo')) .where('addresses.latitude不为NULL,addresses.addressable_type=?',“User”) .near([纬度,经度],(参数[:距离].to_i+1000)) 其次,我使用这些地址将JSON对象呈现回API

我有一个checkitem方法

def checkitem(item)
  begin
    requests = Request.where('item_id = ? AND created_at < ? AND created_at > ?', item.id, (DateTime.now - 1.day), (DateTime.now - 6.months)).pluck(:status)

    if (requests.exists? && requests.count > 2)
      if requests.count('pending') >= 3 && (item.user.current_sign_in_at.present? && item.user.current_sign_in_at < (DateTime.now - 2.weeks))
        false
      else
        true
      end
    elsif (requests == [] || requests.count <= 2)
      true
    elsif (item.user.current_sign_in_at.present? && item.user.current_sign_in_at > (DateTime.now - 2.weeks)) || item.user.created_at > (DateTime.now - 2.weeks)
      true
    else
      false
    end
  rescue
    true
  end
end
def检查项目(项目)
开始
requests=Request.where('item_id=?和created_at<?和created_at>?',item.id,(DateTime.now-1.day),(DateTime.now-6.months)).pull(:status)
如果(requests.exists?&&requests.count>2)
if requests.count('pending')>=3&&(item.user.current\u sign\u in\u at.present?&&item.user.current\u sign\u in\u at<(DateTime.now-2周))
假的
其他的
真的
结束
elsif(requests==[]|| requests.count(DateTime.now-2.weeks))| | item.user.created_at>(DateTime.now-2.weeks)
真的
其他的
假的
结束
营救
真的
结束
结束
然后我呈现我的JSON

@places = Address.where(addressable_type: 'Item').where.not(type_add: nil).near([latitude, longitude], 10)

render json: {markers: @addresses.uniq.map { |address|
                      [{
                        name: address.user.items.first.name,
                        photo: { uri: address.user.items.first.photo.url },
                        id: Item.where(user_id: address.addressable_id).first.id,
                        latitude: address.latitude,
                        longitude: address.longitude,
                        breed: address.user.items.first.breed.id,
                        innactive: checkitem(address.user.items.first) ? false : true,
                        power: (address.user.items.first.requests.count >= 2 && address.user.items.first.requests.last(3).map(&:status).count('pending') < 1) ? true : false,
                      }]
                }.reject { |e| e.nil? }.flatten.first(100)
              }
end
@places=Address.where(可寻址类型:'Item')。where.not(类型添加:nil)。near([纬度,经度],10)
呈现json:{markers:@addresses.uniq.map{| address|
[{
名称:address.user.items.first.name,
照片:{uri:address.user.items.first.photo.url},
id:Item.where(user\u id:address.addressable\u id).first.id,
纬度:地址。纬度,
经度:address.longitude,
品种:address.user.items.first.breed.id,
InActive:checkitem(address.user.items.first)?false:true,
power:(address.user.items.first.requests.count>=2&&address.user.items.first.requests.last(3).映射(&:status).计数('pending')<1)?true:false,
}]
}.拒绝{e{e.nil?}.压扁.第一(100)
}
结束
@地址。解释

    => EXPLAIN for: SELECT addresses.*, 3958.755864232 * 2 * ASIN(SQRT(POWER(SIN((45.501689 - addresses.latitude) * PI() / 180 / 2), 2) + COS(45.501689 * PI() / 180) * COS(addresses.latitude * PI() / 180) * POWER(SIN((-73.567256 - addresses.longitude) * PI() / 180 / 2), 2))) AS distance, MOD(CAST((ATAN2( ((addresses.longitude - -73.567256) / 57.2957795), ((addresses.latitude - 45.501689) / 57.2957795)) * 57.2957795) + 360 AS decimal), 360) AS bearing FROM "addresses" INNER JOIN users ON users.id = addresses.addressable_id INNER JOIN items ON items.user_id = users.id WHERE (items.name IS NOT NULL) AND (items.name <> '') AND (items.visibility = TRUE) AND (items.photo IS NOT NULL) AND (items.photo <> '') AND (addresses.latitude IS NOT NULL AND addresses.addressable_type = 'User' ) AND (addresses.latitude BETWEEN 31.028510688915205 AND 59.97486731108479 AND addresses.longitude BETWEEN -94.21702228070411 AND -52.91748971929589 AND (3958.755864232 * 2 * ASIN(SQRT(POWER(SIN((45.501689 - addresses.latitude) * PI() / 180 / 2), 2) + COS(45.501689 * PI() / 180) * COS(addresses.latitude * PI() / 180) * POWER(SIN((-73.567256 - addresses.longitude) * PI() / 180 / 2), 2)))) BETWEEN 0.0 AND 1000) ORDER BY distance ASC
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      QUERY PLAN
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 Sort  (cost=224.28..224.28 rows=1 width=138)
   Sort Key: (('7917.511728464'::double precision * asin(sqrt((power(sin((((('45.501689'::double precision - addresses.latitude) * '3.14159265358979'::double precision) / '180'::double precision) / '2'::double precision)), '2'::double precision) + (('0.70088823836273'::double precision * cos(((addresses.latitude * '3.14159265358979'::double precision) / '180'::double precision))) * power(sin((((('-73.567256'::double precision - addresses.longitude) * '3.14159265358979'::double precision) / '180'::double precision) / '2'::double precision)), '2'::double precision)))))))
   ->  Nested Loop  (cost=0.11..224.28 rows=1 width=138)
         ->  Nested Loop  (cost=0.06..207.10 rows=39 width=8)
               ->  Seq Scan on items  (cost=0.00..126.62 rows=39 width=4)
                     Filter: ((name IS NOT NULL) AND visibility AND (photo IS NOT NULL) AND ((name)::text <> ''::text) AND ((photo)::text <> ''::text))
               ->  Index Only Scan using users_pkey on users  (cost=0.06..2.06 rows=1 width=4)
                     Index Cond: (id = items.user_id)
         ->  Index Scan using index_addresses_on_addressable_type_and_addressable_id on addresses  (cost=0.06..0.44 rows=1 width=98)
               Index Cond: (((addressable_type)::text = 'User'::text) AND (addressable_id = users.id))
               Filter: ((latitude IS NOT NULL) AND (latitude >= '31.0285106889152'::double precision) AND (latitude <= '59.9748673110848'::double precision) AND (longitude >= '-94.2170222807041'::double precision) AND (longitude <= '-52.9174897192959'::double precision) AND (('7917.511728464'::double precision * asin(sqrt((power(sin((((('45.501689'::double precision - latitude) * '3.14159265358979'::double precision) / '180'::double precision) / '2'::double precision)), '2'::double precision) + (('0.70088823836273'::double precision * cos(((latitude * '3.14159265358979'::double precision) / '180'::double precision))) * power(sin((((('-73.567256'::double precision - longitude) * '3.14159265358979'::double precision) / '180'::double precision) / '2'::double precision)), '2'::double precision)))))) >= '0'::double precision) AND (('7917.511728464'::double precision * asin(sqrt((power(sin((((('45.501689'::double precision - latitude) * '3.14159265358979'::double precision) / '180'::double precision) / '2'::double precision)), '2'::double precision) + (('0.70088823836273'::double precision * cos(((latitude * '3.14159265358979'::double precision) / '180'::double precision))) * power(sin((((('-73.567256'::double precision - longitude) * '3.14159265358979'::double precision) / '180'::double precision) / '2'::double precision)), '2'::double precision)))))) <= '1000'::double precision))
(11 rows)
=>解释:选择地址。*,3958.755864232*2*ASIN(SQRT(幂(SIN((45.501689-地址.纬度)*PI()/180/2),2)+COS(45.501689*PI()/180)*COS(地址.纬度*PI()/180)*幂(SIN(-73.567256-地址.经度)*PI()/180/2))作为距离,MOD/57.2957795),((addresses.latitude-45.501689)/57.2957795))*57.2957795)+360作为小数点),360)作为来自用户上的“地址”内部连接用户的轴承。id=地址。可寻址_id项目上的内部连接项目。user_id=users.id,其中(items.name不为NULL)和(items.visibility=TRUE)和(items.photo不为NULL)和(items.photo“”)和(addresses.latitude不为空,addresses.addressable_type='User')和(addresses.latitude介于31.028510688915205和59.97486731108479之间,addresses.latitude介于-94.2170228070411和-52.91748971929589之间,addresses.755864232*2*ASIN(SQRT(POWER(SIN((45.501689-addresses.latitude)*)*PI()/180/2),2)+COS(45.501689*PI()/180)*COS(addresses.latitude*PI()/180)*幂(SIN((-73.567256-addresses.longitude)*PI()/180/2),介于0.0和1000之间)按距离ASC排序
查询计划
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
@addresses = Address.joins("INNER JOIN users ON users.id = addresses.addressable_id AND addresses.addressable_type = 'User' INNER JOIN items ON items.user_id = users.id")
                    .where.not({ 
                                 items: {
                                   name: [nil, ''],
                                   photo: [nil, ''],
                                   visibility: false
                                 },
                                 addresses: { latitude: nil }
                               })
                    .near([latitude, longitude], (params[:distance].to_i + 1000))
                    .select('addresses.*, items.id AS item_id')
@requests = Request.where(item_id: @addresses.map(&:item_id).uniq).where('created_at < ? AND created_at > ?', (DateTime.now - 1.day), (DateTime.now - 6.months)).to_a
render json: {markers: @addresses.uniq.map { |address|
                  [{
                    name: address.user.items.first.name,
                    photo: { uri: address.user.items.first.photo.url },
                    id: Item.where(user_id: address.addressable_id).first.id,
                    latitude: address.latitude,
                    longitude: address.longitude,
                    breed: address.user.items.first.breed.id,
                    innactive: checkitem(@address.user.items.first, @requests) ? false : true,
                    power: (address.user.items.first.requests.count >= 2 && address.user.items.first.requests.last(3).map(&:status).count('pending') < 1) ? true : false,
                  }]
            }.reject { |e| e.nil? }.flatten.first(100)
          }
end
def checkitem(item, requests)
  begin
    statuses = requests.select { |r| r.item_id = item.id }.map(&:status)

    if (requests.exists? && requests.count > 2)
      if requests.count('pending') >= 3 && (item.user.current_sign_in_at.present? && item.user.current_sign_in_at < (DateTime.now - 2.weeks))
        false
      else
        true
      end
    elsif (requests == [] || requests.count <= 2)
      true
    elsif (item.user.current_sign_in_at.present? && item.user.current_sign_in_at > (DateTime.now - 2.weeks)) || item.user.created_at > (DateTime.now - 2.weeks)
      true
    else
      false
    end
  rescue
    true
  end
end