用于查询的索引

时间:2015-09-11 16:04:40

标签: mysql ruby-on-rails optimization

控制器

@from = params[:from] ? 4.hours.since(Time.zone.parse(params[:from])) : today_start_time
@to = params[:to] ? 4.hours.since(Time.zone.parse(params[:to])) : @from
@franchise = current_user_accessible_franchises_filtered
@orders_type = Restaurant::DELIVERY_TYPES.detect { |t| t == params[:orders_type]} || Restaurant::DELIVERY_TYPES.first
@limit = (params[:limit] || 250).to_i

@to = 48.hours.since(@to) if @to == @from && @from == today_start_time

start_time = @from.utc.strftime('%Y-%m-%d %H:%M')
end_time = 24.hours.since(@to).utc.strftime('%Y-%m-%d %H:%M')

@orders = Order
  .includes(:address, :franchise, :customer, :ordered_items, :rests, :driver)
  .where(
    "((orders.created_at >= ? AND orders.created_at <= ?) OR (orders.delivery_target >= ? AND orders.delivery_target <= ?)) AND orders.franchise_id in (?) AND orders.delivery_type = ?",
    start_time, end_time, start_time, end_time, @franchise, @orders_type
  )
  .order("orders.status desc, orders.id desc")

登录

  

(23732.8ms)SELECT COUNT(DISTINCT ordersid)FROM orders LEFT   外联addresses addressesid = ordersaddress_id   LEFT OUTER JOIN franchises ON franchisesid =   ordersfranchise_id LEFT OUTER JOIN customers ON   customersid = orderscustomer_id LEFT OUTER JOIN   ordered_items ordered_itemsorder_id = ordersid左   外部加入ordered_items ordered_items_orders_join开启   ordered_items_orders_joinorder_id = ordersid LEFT OUTER JOIN   restaurants restaurantsid =   ordered_items_orders_joinrestaurant_id LEFT OUTER JOIN drivers   在driversid = ordersdriver_id WHERE(((orders.created_at&gt; =   &#39; 2015-03-01 10:00&#39; AND orders.created_at&lt; =&#39; 2015-03-04 10:00&#39;)或   (orders.delivery_target&gt; =&#39; 2015-03-01 10:00&#39; AND   orders.delivery_target&lt; =&#39; 2015-03-04 10:00&#39;))AND orders.franchise_id   在   (3,31,4,22,37,2,36,17,34,30,19,20,21,18,27,13,25,16,35,24,32,33,1,12,28 ,23,14,26,29,8,11)   AND orders.delivery_type =&#39;先生。送餐服务&#39;)

EXPLAIN EXTENDED

mysql> EXPLAIN EXTENDED
 SELECT  DISTINCT `orders`.id
    FROM  `orders`
    LEFT OUTER JOIN  `addresses`     ON `addresses`.`id` = `orders`.`address_id`
    LEFT OUTER JOIN  `franchises`    ON `franchises`.`id` = `orders`.`franchise_id`
    LEFT OUTER JOIN  `customers`     ON `customers`.`id` = `orders`.`customer_id`
    LEFT OUTER JOIN  `ordered_items` ON `ordered_items`.`order_id` = `orders`.`id`
    LEFT OUTER JOIN  `ordered_items` `ordered_items_orders_join`
                                     ON `ordered_items_orders_join`.`order_id` = `orders`.`id`
    LEFT OUTER JOIN  `restaurants`   ON `restaurants`.`id` = `ordered_items_orders_join`.`restaurant_id`
    LEFT OUTER JOIN  `drivers`       ON `drivers`.`id` = `orders`.`driver_id`
    WHERE  ( ( (orders.created_at >= '2015-02-01 10:00'
           AND  orders.created_at <= '2015-02-04 10:00')
                     OR  (orders.delivery_target >= '2015-02-01 10:00'
                     AND  orders.delivery_target <= '2015-02-04 10:00') )
              AND  orders.franchise_id in (3,31,4,22,37,2,36,17,34,30,
                       19,20,21,18,27,13,25,16,35,24,32,33,1,12,28,23,14,26,29, 8,11 )
              AND  orders.delivery_type = 'Mr. Delivery Restaurant'
           )
    ORDER BY  orders.status desc,
              orders.id desc
    LIMIT  250;

+----+-------------+---------------------------+--------+------------------------------------------------------------------------------------------------------------------------------+---------------------------------+---------+---------------------------------------------------------+--------+----------+----------------------------------------------+
| id | select_type | table                     | type   | possible_keys                                                                                                                | key                             | key_len | ref                                                     | rows   | filtered | Extra                                        |
+----+-------------+---------------------------+--------+------------------------------------------------------------------------------------------------------------------------------+---------------------------------+---------+---------------------------------------------------------+--------+----------+----------------------------------------------+
|  1 | SIMPLE      | orders                    | ref    | index_orders_on_created_at,index_orders_on_delivery_target,index_orders_on_franchise_id,index_orders_on_delivery_type,my_idx | index_orders_on_delivery_type   | 77      | const                                                   | 549769 |   100.00 | Using where; Using temporary; Using filesort |
|  1 | SIMPLE      | addresses                 | eq_ref | PRIMARY                                                                                                                      | PRIMARY                         | 4       | mrd_staging_new.orders.address_id                       |      1 |   100.00 | Using index; Distinct                        |
|  1 | SIMPLE      | franchises                | eq_ref | PRIMARY                                                                                                                      | PRIMARY                         | 4       | mrd_staging_new.orders.franchise_id                     |      1 |   100.00 | Using index; Distinct                        |
|  1 | SIMPLE      | customers                 | eq_ref | PRIMARY                                                                                                                      | PRIMARY                         | 4       | mrd_staging_new.orders.customer_id                      |      1 |   100.00 | Using index; Distinct                        |
|  1 | SIMPLE      | ordered_items             | ref    | index_ordered_items_on_order_id                                                                                              | index_ordered_items_on_order_id | 5       | mrd_staging_new.orders.id                               |      2 |   100.00 | Using index; Distinct                        |
|  1 | SIMPLE      | ordered_items_orders_join | ref    | index_ordered_items_on_order_id                                                                                              | index_ordered_items_on_order_id | 5       | mrd_staging_new.orders.id                               |      2 |   100.00 | Distinct                                     |
|  1 | SIMPLE      | restaurants               | eq_ref | PRIMARY                                                                                                                      | PRIMARY                         | 4       | mrd_staging_new.ordered_items_orders_join.restaurant_id |      1 |   100.00 | Using index; Distinct                        |
|  1 | SIMPLE      | drivers                   | eq_ref | PRIMARY                                                                                                                      | PRIMARY                         | 4       | mrd_staging_new.orders.driver_id                        |      1 |   100.00 | Using index; Distinct                        |
+----+-------------+---------------------------+--------+------------------------------------------------------------------------------------------------------------------------------+---------------------------------+---------+---------------------------------------------------------+--------+----------+----------------------------------------------+
8 rows in set, 1 warning (0.00 sec)
订单表上的

指数

| Table  | Non_unique | Key_name                              | Seq_in_index | Column_name           | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+--------+------------+---------------------------------------+--------------+-----------------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| orders |          0 | PRIMARY                               |            1 | id                    | A         |      935943 |     NULL | NULL   |      | BTREE      |         |               |
| orders |          1 | index_orders_on_delivered_at          |            1 | delivered_at          | A         |      935943 |     NULL | NULL   | YES  | BTREE      |         |               |
| orders |          1 | index_orders_on_updated_at            |            1 | updated_at            | A         |      935943 |     NULL | NULL   | YES  | BTREE      |         |               |
| orders |          1 | index_orders_on_created_at            |            1 | created_at            | A         |      935943 |     NULL | NULL   | YES  | BTREE      |         |               |
| orders |          1 | index_orders_on_pickup_at             |            1 | pickup_at             | A         |      935943 |     NULL | NULL   | YES  | BTREE      |         |               |
| orders |          1 | index_orders_on_coupon_id             |            1 | coupon_id             | A         |       14856 |     NULL | NULL   | YES  | BTREE      |         |               |
| orders |          1 | index_orders_on_driver_id             |            1 | driver_id             | A         |        4159 |     NULL | NULL   | YES  | BTREE      |         |               |
| orders |          1 | index_orders_on_delivery_target       |            1 | delivery_target       | A         |      935943 |     NULL | NULL   | YES  | BTREE      |         |               |
| orders |          1 | index_orders_on_franchise_id          |            1 | franchise_id          | A         |          48 |     NULL | NULL   | YES  | BTREE      |         |               |
| orders |          1 | idx_for_customers_report              |            1 | customer_id           | A         |      935943 |     NULL | NULL   | YES  | BTREE      |         |               |
| orders |          1 | idx_for_customers_report              |            2 | delivered_at          | A         |      935943 |     NULL | NULL   | YES  | BTREE      |         |               |
| orders |          1 | idx_for_customers_report              |            3 | created_at            | A         |      935943 |     NULL | NULL   | YES  | BTREE      |         |               |
| orders |          1 | idx_for_customers_report              |            4 | status                | A         |      935943 |     NULL | NULL   |      | BTREE      |         |               |
| orders |          1 | idx_for_customers_report              |            5 | franchise_id          | A         |      935943 |     NULL | NULL   | YES  | BTREE      |         |               |
| orders |          1 | orders_fetch_index_for_revenue_report |            1 | id                    | A         |      935943 |     NULL | NULL   |      | BTREE      |         |               |
| orders |          1 | orders_fetch_index_for_revenue_report |            2 | created_at            | A         |      935943 |     NULL | NULL   | YES  | BTREE      |         |               |
| orders |          1 | orders_fetch_index_for_revenue_report |            3 | delivered_at          | A         |      935943 |     NULL | NULL   | YES  | BTREE      |         |               |
| orders |          1 | orders_fetch_index_for_revenue_report |            4 | status                | A         |      935943 |     NULL | NULL   |      | BTREE      |         |               |
| orders |          1 | orders_fetch_index_for_revenue_report |            5 | franchise_id          | A         |      935943 |     NULL | NULL   | YES  | BTREE      |         |               |
| orders |          1 | orders_fetch_index_for_revenue_report |            6 | customer_id           | A         |      935943 |     NULL | NULL   | YES  | BTREE      |         |               |
| orders |          1 | orders_fetch_index_for_revenue_report |            7 | address_id            | A         |      935943 |     NULL | NULL   | YES  | BTREE      |         |               |
| orders |          1 | index_orders_on_address_id            |            1 | address_id            | A         |      935943 |     NULL | NULL   | YES  | BTREE      |         |               |
| orders |          1 | index_orders_on_customer_id           |            1 | customer_id           | A         |      935943 |     NULL | NULL   | YES  | BTREE      |         |               |
| orders |          1 | index_orders_on_delivery_type         |            1 | delivery_type         | A         |           4 |     NULL | NULL   |      | BTREE      |         |               |
| orders |          1 | index_orders_on_status                |            1 | status                | A         |           8 |     NULL | NULL   |      | BTREE      |         |               |
| orders |          1 | index_orders_on_should_pay_restaurant |            1 | should_pay_restaurant | A         |           4 |     NULL | NULL   | YES  | BTREE      |         |               |
| orders |          1 | my_idx                                |            1 | created_at            | A         |      935943 |     NULL | NULL   | YES  | BTREE      |         |               |
| orders |          1 | my_idx                                |            2 | delivery_target       | A         |      935943 |     NULL | NULL   | YES  | BTREE      |         |               |
| orders |          1 | my_idx                                |            3 | franchise_id          | A         |      935943 |     NULL | NULL   | YES  | BTREE      |         |               |
| orders |          1 | my_idx                                |            4 | delivery_type         | A         |      935943 |     NULL | NULL   |      | BTREE      |         |               |
| orders |          1 | my_idx                                |            5 | status                | A         |      935943 |     NULL | NULL   |      | BTREE      |         |               |
| orders |          1 | my_idx                                |            6 | id                    | A         |      935943 |     NULL | NULL   |      | BTREE      |         |               |

总数量

mysql> select count(*) from orders;
+----------+
| count(*) |
+----------+
|   965520 |
+----------+
1 row in set (0.32 sec)

我尝试添加综合索引

create index my_idx on orders(created_at, delivery_target, franchise_id, delivery_type);

甚至

create index my_idx on orders(created_at, delivery_target, franchise_id, delivery_type, status, id);

但没有成功。

有什么想法吗?

1 个答案:

答案 0 :(得分:1)

INDEX(delivery_type,  -- because it is  "= constant"
      franchise_id)   -- the only other viable column

为隐藏在OR中的任何列编制索引实际上是徒劳的。

我在执行ORDER BY status时对您的DISTINCT id提出质疑,但未提及status

可能能够通过将OR变为UNION

来加快速度
      ( SELECT  orders.status, orders.id
            FROM  ...
            JOIN  ...
            WHERE  orders.created_at ...
              AND  ...
            ORDER BY  ...
            LIMIT  250 
      )
    UNION  DISTINCT 
      ( SELECT  orders.status, orders.id
            FROM  ...
            JOIN  ...
            WHERE  orders.delivery_target ... -- note difference
              AND  ...
            ORDER BY  ...
            LIMIT  250 
      )
    ORDER BY  status DESC, id DESC -- yes, again
    LIMIT  250; -- yes, again 

但是为了使这项改革工作顺利进行,需要有新的指标。我不确定是否这些

INDEX(delivery_type, franchise_id, created_at),
INDEX(delivery_type, franchise_id, delivery_target),

或这些

INDEX(delivery_type, created_at),
INDEX(delivery_type, delivery_target),

会更好。全部加4;请EXPLAIN查看它使用的内容。