How do you optimize a MySQL query that joins on it

2019-09-15 03:49发布

问题:

I have the following query that is starting to become slow as the size of the DB table increases:

SELECT  
    t.*, 
    e.TranslatedValue AS EnglishValue
FROM (
    SELECT DISTINCT PropertyKey 
    FROM Translations
) grouper
JOIN Translations t 
    ON t.TranslationId = (
        SELECT TranslationId 
        FROM Translations gt
        WHERE gt.PropertyKey = grouper.PropertyKey 
            AND gt.Locale = 'es' 
            AND gt.Priority = 3
        ORDER BY gt.ModifiedDate DESC 
        LIMIT 1
    )
INNER JOIN Translations e 
    ON t.EnglishTranslationId = e.TranslationId 
ORDER BY t.ReviewerValidated, PropertyKey

First, I am selecting everything from Translations, joined with itself to get me the corresponding English value also.

Then, I then want to limit my results to only one per PropertyKey. This is like a group by except I need to pick a specific record to be the one returned (instead of the way group by just gives me the first one it finds). That is why I have the inner query that just returns one TranslationId.

When I run explain I get the following info:

Is there a way I can return the same set of results without having to have MySQL use a slower derived table? Thanks!

UPDATE: I created an SQL Fiddle with a schema and sample data. You can run my query for yourself to see the results it gives. I need to be able to get the same results, hopefully in a faster way. http://sqlfiddle.com/#!2/44eb0/3/0

回答1:

I think you want the most recent TranslatedValue for the given local and priority that matches PropertyKey in a record.

If so, the following does what you want, using a single correlated subquery:

 select t.*,
        (select t2.TranslatedValue
         from Translations t2
         where t.PropertyKey = t2.PropertyKey and
               t2.Locale = 'es' and
               t2.Priority = 3
         order by t.ModifiedDate desc
         limit 1
        ) as EnglishValue
 from Translations t
 having EnglishValue is not NULL
 ORDER BY t.ReviewerValidated, PropertyKey;

(The having clause eliminates records with no translation.)

If so, then an index on Translations(PropertyKey, Locale, Priority, ModifiedDate) should speed up the query.