如何在rails应用程序中减少sql查询执行时间?

时间:2012-01-07 06:27:12

标签: ruby-on-rails postgresql

我的查询为

select i.shipping_charges, i.shipping_carrier, i.shipping_method, 
       i.tracking_number, i.origin_zip_code, i.origin_city, 
       i.origin_country, i.weight_value, i.weight_unit, 
       i.delivery_date, i.shipping_date, i.shipping_description, 
       i.delivery_zip_code, i.delivery_street_add, i.item_id, 
       i.start_at, i.end_at, i.id 
from (items it 
      left join item_shipping_details i on it.id = i.item_id) 
left join users u on u.id = it.alert_user_id 
where it.user_id=4 AND i.id in (35,602,1175,1176,1177,604,1178,1174,
                                1165,1179,930,1160,917,914,925,909,920,1147,910)  
                   AND (it.alert_user_id is null OR u.user_type in (2,3))  
                   AND (it.outbound != true OR it.outbound is null)

在postgresql中运行需要8ms。 请告诉任何其他替代解决方案吗?

3 个答案:

答案 0 :(得分:2)

关于你的查询,有些事情很奇怪或者说是荒谬的。

  • FROM列表中的主要表格为items,但您在SELECT列表主表中没有单列。你拥有它的方式,它最多只添加一堆只有NULL值的行,同时混淆查询规划器。你不想要那个。
    我颠倒了顺序并将item_shipping_details作为主表。这将很多更快。

  • LEFT JOINitems之间的item_shipping_details是矛盾的,因为其他条款无论如何都需要来自两个表格的行。简化为普通JOIN 也使前两个表的外观顺序再次无关 功能

  • 删除了第一个JOIN周围的括号,因为没有用。

  • 简化(it.outbound != true OR it.outbound is null)it.outbound IS NOT TRUE

SELECT i.shipping_charges, i.shipping_carrier, i.shipping_method, 
       i.tracking_number, i.origin_zip_code, i.origin_city, 
       i.origin_country, i.weight_value, i.weight_unit, 
       i.delivery_date, i.shipping_date, i.shipping_description, 
       i.delivery_zip_code, i.delivery_street_add, i.item_id, 
       i.start_at, i.end_at, i.id 
FROM   item_shipping_details i
JOIN   items it ON it.id = i.item_id
LEFT   JOIN users u on u.id = it.alert_user_id 
WHERE  i.id IN (35,602,1175,1176,1177,604,1178,1174,1165,1179,
                930,1160,917,914,925,909,920,1147,910)
AND    it.user_id = 4
AND    it.outbound IS NOT TRUE
AND   (it.alert_user_id IS NULL OR u.user_type IN (2,3))

应该大大增加执行时间 ...性能。 :)

答案 1 :(得分:0)

假设您的意思是减少查询执行时间,打开相应列的索引可以大大加快结果检索速度。

答案 2 :(得分:0)

你的查询的这一部分正在进行中

IN (35,602,1175,1176,1177,604,1178,1174,1165,1179,
            930,1160,917,914,925,909,920,1147,910)

YES“子查询”有很多种方法:

  1. 使用JOIN()和更少的INCLUDE()。
  2. 尽量避免使用子查询并找到([array])
  3. 使用缓存
  4. 您可能会在rails doc中找到更多更好的选项 http://guides.rubyonrails.org/active_record_querying.html