私は長い間この問題に取り組んできました。このクエリは、小さなデータセットにかなり高速に動作しますが、テーブルには、それが実行に数分に30代から取る100K +行に育つとき:"nullではない"を使用する左結合クエリの最適化
SELECT accounts.id
, accounts.name
, ..etc..
FROM accounts
LEFT JOIN (
SELECT distinct secr.record_id as id
FROM securitygroups secg
INNER JOIN securitygroups_users secu
ON secg.id = secu.securitygroup_id
AND secu.deleted = 0
AND secu.user_id = 'seed_chris_id'
INNER JOIN securitygroups_records secr
ON secg.id = secr.securitygroup_id
AND secr.deleted = 0
AND secr.module = 'Accounts'
WHERE secg.deleted = 0
) securitygroup_join ON securitygroup_join.id = accounts.id
WHERE ((accounts.assigned_user_id ='seed_chris_id'
OR securitygroup_join.id is not null))
AND accounts.deleted=0
ORDER BY
accounts.date_entered
DESC LIMIT 0,21
基本的にはユーザーがレコード(アカウントを所有しているすべての行を返す必要があります。 assigned_user_id)、またはレコードに関連付けられたグループのメンバーです(securitygroup_join.idはnullではありません)。この問合せは、フレームワークによって特定の方法で構築され、いくつかの制約に直面します。簡単に実装できない解決策は、これをUNIONに変更することです。そのルートを避けたいですか?過去には "where ... in"という句がありましたが、それはさらに悪化しました。必要に応じてjoin、where句を追加したり、インデックスを操作したりすることはできますが、クエリ構造の他の劇的な変更は簡単にはできません。
+1:確かに試してみる価値があります。 – MatBailie
securitygroups_recordsテーブルの700k行のデータベースに対して、提案された変更が約3.2秒で実行されていたのに対し、元のクエリが17.8秒で実行されていました。私はそれが良い改善だと思います:)。私は最初の場所に存在するとは思わなかった。ありがとう! – egg
素晴らしい!お役に立てて嬉しいです。 –