How to optimize MySQL Views

11,178

If it is at all possible to remove those joins remove them. Replacing them with subquerys will speed it up a lot.

you could also try running something like this to see if it has any speed difference at all.

select [stuff] from orders as ord 
left join (
  create view calc_order_status as
  select ord.id AS order_id,
  (sum(itm.items * itm.item_price) + ord.delivery_cost) AS total_total
  from orders ord 
  left join order_items itm on itm.order_id = ord.id
  group by ord.id
) as ors on (ors.order_id = ord.id) 
Share:
11,178
jms
Author by

jms

Updated on June 04, 2022

Comments

  • jms
    jms almost 2 years

    I have some querys using views, and these run a lot slower than I would expect them to given all relevant tables are indexed (and not that large anyway).

    I hope I can explain this:

    My main Query looks like this (grossly simplified)

    select [stuff] from orders as ord 
    left join calc_order_status as ors on (ors.order_id = ord.id)
    

    calc_order_status is a view, defined thusly:

    create view calc_order_status as
    select ord.id AS order_id,
    (sum(itm.items * itm.item_price) + ord.delivery_cost) AS total_total
    from orders ord 
    left join order_items itm on itm.order_id = ord.id
    group by ord.id
    

    Orders (ord) contain orders, order_items contain the individual items associated with each order and their prices.

    All tables are properly indexed, BUT the thing runs slowly and when I do a EXPLAIN I get

      # id  select_type  table  type  possible_keys  key  key_len  ref  rows  Extra  
      1 1 PRIMARY ord ALL customer_id NULL NULL NULL 1002 Using temporary; Using filesort 
      2 1 PRIMARY <derived2> ALL NULL NULL NULL NULL 1002   
      3 1 PRIMARY cus eq_ref PRIMARY PRIMARY 4 db135147_2.ord.customer_id 1 Using where 
      4 2 DERIVED ord ALL NULL NULL NULL NULL 1002 Using temporary; Using filesort 
      5 2 DERIVED itm ref order_id order_id 4 db135147_2.ord.id 2   
    

    My guess is, "derived2" refers to the view. The individual items (itm) seem to work fine, indexed by order _ id. The problem seems to be Line # 4, which indicates that the system doesn't use a key for the orders table (ord). But in the MAIN query, the order id is already defined: left join calc_order_status as ors on (ors.order _ id = ord.id) and ord.id (both in the main query and within the view) refer to the primary key.

    I have read somewhere than MySQL simpliy does not optimize views that well and might not utilize keys under some conditions even when available. This seems to be one of those cases.

    I would appreciate any suggestions. Is there a way to force MySQL to realize "it's all simpler than you think, just use the primary key and you'll be fine"? Or are views the wrong way to go about this at all?