web-dev-qa-db-ja.com

サブクエリvsジョインと場所-どちらが速いですか?

私は同じ結果を与える2つのSQLを持っています:

クエリ1:

SELECT
u.*, COUNT(po.order_id) products_count
FROM (SELECT * FROM orders o WHERE o.date >= (CURRENT_DATE() - INTERVAL 1 MONTH)) o
LEFT JOIN products_orders po ON po.order_id=o.id
JOIN users u ON u.id=o.user_id
GROUP BY po.order_id

とクエリ2:

SELECT
u.*, o.id order_id, COUNT(po.order_id) products_count
FROM users u
JOIN orders o ON o.user_id=u.id
LEFT JOIN products_orders po ON po.order_id=o.id
WHERE o.date >= (CURRENT_DATE() - INTERVAL 1 MONTH)
GROUP BY po.order_id

どっちが速い? Query Explainsはそれらが等しいことを示しています...皆さんはどう思いますか? Query 1Query 2

1
breq

あなたの集計はあまり意味がありません(そしてほとんどのデータベース、そしてMySQLの最新バージョンでさえそれを拒否します-参照 ONLY_FULL_GROUP_BY )...おそらくGROUP BY o.user_id、(そして、おそらく、orders_id、ただしそれをSELECT句にも追加します。このようにすると、少し速くなります。

SELECT
    u.*, c.order_count, c.products_count
FROM
    (SELECT
         o.user_id, 
         COUNT(DISTINCT o.id) AS order_count, 
         COUNT(po.order_id)   AS products_count
    FROM
        orders o
        LEFT JOIN products_orders po ON po.order_id = o.id
    WHERE 
        o.date >= (now() - INTERVAL 1 MONTH)        
    GROUP BY
        o.user_id
    ) AS c
    JOIN users u ON u.id = c.user_id ;

このクエリの実行プランは異なり、派生テーブル(MySQLまたはMariaDBは必ずしも非常に優れているわけではありません)を使用しますが、ユーザーは一度だけです。

詳細はdbfiddle hereで確認できます。

1
joanolo