0

複数の結合を行うクエリで問題が発生し、大きなレコードセットでは非常に遅くなります。クエリは次のとおりです。

SELECT 
    order_headers.*,
    SUM(order_details.cost) AS amount,
    CONCAT(organizations.card_first_name,
            ' ',
            organizations.card_last_name) AS card_name
FROM
    order_headers
        INNER JOIN
    organizations ON order_headers.organization_id = organizations.id
        LEFT JOIN
    order_details ON order_details.order_header_id = order_headers.id
        LEFT JOIN
    user_accounts ON user_accounts.organization_id = organizations.id
        AND organizations.is_single_user = 1
WHERE
    (status IN ('UNCHARGED' , 'ERROR'))
GROUP BY order_headers.id
HAVING SUM(order_details.cost) > 0
ORDER BY IF(organizations.is_single_user = 1,
    (user_accounts.first_name + ' ' + user_accounts.last_name),
    organizations.name) ASC
LIMIT 100 OFFSET 0

クエリから削除できるものがいくつかありますが (ただし、アプリが機能するためには必要です)、クエリを最大 0.183 秒まで高速化します。それらには以下が含まれます:

  1. order by 句を完全に削除します。何らかの理由で、MySQL は user_accounts テーブルからフィールドを取得することを好みません。しかし、これは姓/名でソートできないことを意味します。連結を削除するだけでは不十分です。パフォーマンスを向上させるには、order 句から first AND last を削除する必要があります。私が検討したオプションの 1 つは、organizations.name フィールドにユーザーの姓名を「キャッシュ」することです。ただし、organizations.name だけで並べ替えたクエリを実行しても、パフォーマンスは低下します。そして、アプリケーション コードをリファクタリングする必要がありました。
  2. すべての参照、order_details テーブルの包含を削除します (これは実際には約 101K レコードの最大のテーブルです)。しかし、注文の詳細の合計はありません。また、合計が 0 より大きい order_headers に結果を限定していません。

どんな助けでも大歓迎です。

4

1 に答える 1