[Solved] optimization of a SQL query

How to optimize this SQL query?

In case you have your own slow SQL query, you can optimize it automatically here.

For the query above, the following recommendations will be helpful as part of the SQL tuning process.
You'll find 3 sections below:

  1. Description of the steps you can take to speed up the query.
  2. The optimal indexes for this query, which you can copy and create in your database.
  3. An automatically re-written query you can copy and execute in your database.
The optimization process and recommendations:
  1. Avoid OR Conditions By Using UNION (modified query below): In mosts cases, filtering using the OR operator cannot be applied using indexes. A more optimized alternative will be to split the query to two parts combined with a UNION clause, while each query holds one part of the original OR condition.
  2. Create Optimal Indexes (modified query below): The recommended indexes are an integral part of this optimization effort and should be created before testing the execution duration of the optimized query.
  3. Remove Redundant Left Joins (modified query below): Redundant LEFT JOINs (e.g. `totrihrl_temp`) were detected in the query. Removing them will result in a performance improvement. In some cases, JOINs become redundant after an optimization is applied, such as when converting OR conditions to a UNION clause.
  4. Remove Redundant Left Joins (modified query below): Redundant LEFT JOINs (e.g. `totfrhrl_temp`) were detected in the query. Removing them will result in a performance improvement. In some cases, JOINs become redundant after an optimization is applied, such as when converting OR conditions to a UNION clause.
  5. Use UNION ALL instead of UNION (query line: 89): Always use UNION ALL unless you need to eliminate duplicate records. By using UNION ALL, you'll avoid the expensive distinct operation the database applies when using a UNION clause.
Optimal indexes for this query:
ALTER TABLE `price` ADD INDEX `price_idx_sku` (`sku`);
ALTER TABLE `totfrhrl` ADD INDEX `totfrhrl_idx_eta` (`eta`);
ALTER TABLE `totfrhrl` ADD INDEX `totfrhrl_idx_command` (`command`);
ALTER TABLE `totfrhrl` ADD INDEX `totfrhrl_idx_dispo` (`dispo`);
ALTER TABLE `totfrhrl_temp` ADD INDEX `totfrhrl_temp_idx_sku_eta` (`sku`,`eta`);
ALTER TABLE `totfrhrl_temp` ADD INDEX `totfrhrl_temp_idx_sku_command` (`sku`,`command`);
ALTER TABLE `totfrhrl_temp` ADD INDEX `totfrhrl_temp_idx_sku_dispo` (`sku`,`dispo`);
ALTER TABLE `totrihrl` ADD INDEX `totrihrl_idx_eta` (`eta`);
ALTER TABLE `totrihrl` ADD INDEX `totrihrl_idx_command` (`command`);
ALTER TABLE `totrihrl` ADD INDEX `totrihrl_idx_dispo` (`dispo`);
ALTER TABLE `totrihrl_temp` ADD INDEX `totrihrl_temp_idx_sku_eta` (`sku`,`eta`);
ALTER TABLE `totrihrl_temp` ADD INDEX `totrihrl_temp_idx_sku_command` (`sku`,`command`);
ALTER TABLE `totrihrl_temp` ADD INDEX `totrihrl_temp_idx_sku_dispo` (`sku`,`dispo`);
The optimized query:
SELECT
        DISTINCT CONCAT(p.sku,
        '_IM') AS REF,
        CONCAT(p.ref_fabriq,
        ' / FR ',
        COALESCE(frtemp.dispo,
        0),
        ' - EU ',
        COALESCE(eutemp.dispo,
        0),
        ' / CDE : FR ',
        COALESCE(frtemp.command,
        0),
        ' - EU ',
        COALESCE(eutemp.command,
        0),
        ' / ETA : FR ',
        COALESCE(frtemp.eta,
        ''),
        ' - EU ',
        COALESCE(eutemp.eta,
        ''),
        '/ DATE FP : ',
        p.fin_promo,
        ' / ',
        p.class_prod,
        ' / ',
        p.crc) AS DESCRIPTION 
    FROM
        price AS p 
    LEFT JOIN
        totfrhrl_temp frtemp 
            ON p.sku = frtemp.sku 
    LEFT JOIN
        totrihrl_temp eutemp 
            ON p.sku = eutemp.sku 
    WHERE
        p.sku IN (
            SELECT
                fr.sku 
            FROM
                totfrhrl AS fr 
            LEFT JOIN
                totfrhrl_temp frtemp 
                    ON fr.sku = frtemp.sku 
            WHERE
                fr.eta != frtemp.eta 
            UNION
            SELECT
                eu.sku 
            FROM
                totrihrl AS eu 
            LEFT JOIN
                totrihrl_temp eutemp 
                    ON eu.sku = eutemp.sku 
            WHERE
                eu.eta != eutemp.eta 
            UNION
            DISTINCT SELECT
                fr.sku 
            FROM
                totfrhrl AS fr 
            LEFT JOIN
                totfrhrl_temp frtemp 
                    ON fr.sku = frtemp.sku 
            WHERE
                fr.command != frtemp.command 
            UNION
            DISTINCT SELECT
                eu.sku 
            FROM
                totrihrl AS eu 
            LEFT JOIN
                totrihrl_temp eutemp 
                    ON eu.sku = eutemp.sku 
            WHERE
                eu.command != eutemp.command 
            UNION
            DISTINCT SELECT
                fr.sku 
            FROM
                totfrhrl AS fr 
            LEFT JOIN
                totfrhrl_temp frtemp 
                    ON fr.sku = frtemp.sku 
            WHERE
                fr.dispo != frtemp.dispo 
            UNION
            DISTINCT SELECT
                eu.sku 
            FROM
                totrihrl AS eu 
            LEFT JOIN
                totrihrl_temp eutemp 
                    ON eu.sku = eutemp.sku 
            WHERE
                eu.dispo != eutemp.dispo
        )

Related Articles



* original question posted on StackOverflow here.