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