简体   繁体   中英

MYSQL View Query Performance Issue

I have 5 SQL tables

  • store
  • staff
  • departments
  • sold_items
  • staff_rating

I created a view that JOINs this four of the tables together. The last table (staff_rating),I want to get the rating column at a time close to when items was sold (sold_items.date) for the view rows. I have tried the following SQL Queries which works but have performance issues.

SQL QUERY 1

SELECT s.name,
       s.country,
       d.name,
       si.item, 
       si.date, 
       (SELECT rating 
        FROM staff_ratings 
        WHERE staff_id = s.id 
        ORDER BY DATEDIFF(date, si.date) LIMIT 1) AS rating, 
       st.name, 
       st.owner
   FROM store st
   LEFT OUTER JOIN staff s ON s.store_id = st.id
   LFET JOIN departments d ON d.store_id = st.id
   LEFT JOIN sold_items si ON si.store_id = st.id

SQL QUERY 2

SELECT s.name,
       s.country,
       d.name,
       si.item, 
       si.date, 
       si.rating , 
       st.name, 
       st.owner
FROM store st
LEFT OUTER JOIN staff s ON s.store_id = st.id
LFET JOIN departments d ON d.store_id = st.id
LEFT JOIN (SELECT *,
                  (SELECT rating 
                   FROM staff_ratings 
                   WHERE staff_id = si.staff_id 
                   ORDER BY DATEDIFF(date, si.date) LIMIT 1) AS rating 
           FROM sold_items) si ON si.store_id = st.id

SQL Query 2 is faster than SQL Query 1. But Both still have performance issue. Appreciate help for a query with better performance. Thanks in advance.

Your query doesn't look right to me (as mentioned in a comment on the original post; lacking staff_id in the join on the sales, etc)

Ignoring that, one of your biggest performance hits is likely to be this...

ORDER BY DATEDIFF(date, si.date) LIMIT 1

That order by can only be answered by comparing EVERY record for that staff member to the current sales record.

What you ideally want to be able to do is find the appropriate staff rating from an index, and not to have to run computations that involve dates from both the ratings table and the sales table.

If, for example, you wanted "the most recent rating BEFORE the sale", the query can be substantially improved...

SELECT
   s.name,
   s.country,
   d.name,
   si.item, 
   si.date, 
   (
     SELECT sr.rating 
       FROM staff_ratings sr
      WHERE sr.staff_id = s.id
        AND sr.date <= si.date
   ORDER BY sr.date DESC
      LIMIT 1
   )
    AS rating, 
   st.name, 
   st.owner
FROM store st
LEFT JOIN staff s ON s.store_id = st.id
LFET JOIN departments d ON d.store_id = st.id
LEFT JOIN sold_items si ON si.store_id = st.id

Then, with an index for staff_ratings(staff_id, date, rating) the optimiser can very quickly look up which rating to use, without having to scan Every Single Rating for that staff member.

Why DATEDIFF ? Would something like this work better? If so, the given index will make it work much faster.

WHERE staff_id = s.id
  AND s.date >= s1.date
ORDER BY s.date
LIMIT 1

And INDEX(staff_id, date)

Do you need LEFT JOIN ? Perhaps plain JOIN ?

d may benefit from INDEX(store_id, name)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM