Search code examples
mysqlsqldatabase-performance

Unused columns in a view / subquery (MySQL)


If the result set of a query does not use a field produced by a subquery or view, is that field still processed by the subquery? I have a lot of views in my database that are used in many places, but the exact set of fields needed varies by context. Rather than duplicating similar queries in each context (with the appropriate field group), I've been using views that may contain extra fields for each context. It looks like these extra views do affect performance in MySQL (I experience a 1/4 improvement in performance by removing the extra field in the example below). Any solutions? Different database (i.e. Oracle)?

See below for an example; the charge_off_date field could clearly be skipped when running the view, but it still affects performance.

select 
    l.loan_id, last_payment_date
from
    loans as l
        left join
    (select 
        loan_id,
            max(ph.received_d) as last_payment_date,
            max(case
                when ph.co = 1 then coalesce(ph.received_d, ph.month)
                else null
            end) as charge_off_date
    from
        payment_history as ph) as payment_stats ON payment_stats.loan_id = l.loan_id

Solution

  • MySQL instantiates (non-correlated) subqueries and creates an execution plan for views that is not optimized beyond the view. In other words, MySQL will not optimize in this case.

    Other databases are smarter about optimization. That does not mean they will do the right thing, but there is a chance.

    I would suggest, though, that you write the query as just a join with an aggregation and no subquery:

    select l.loan_id, max(ph.received_d) as last_payment_date,
           max(case when ph.co = 1 then coalesce(ph.received_d, ph.month)
               end) as charge_off_date
    from loans l left join
         payment_history ph
         on ph.loan_id = l.loan_id
    group by l.loan_id;
    

    There is no need for the subquery in the from clause (and this isn't allowed in a MySQL view anyway). Plus, if you have a where clause, this should take advantage of the where clause and improve performance.