複雑なドクトリンクエリにおける左結合を遅くするための可能な解決策
P粉517475670
P粉517475670 2023-09-02 18:55:02
0
2
719
<p>かなり複雑なデータセットを取得する symfony リポジトリ メソッドがあり、エクスポート マネージャー クラスによって CSV ファイルに配置されます。エクスポート ジョブを処理するコード全体を記載するつもりはありませんが、クエリが遅くなるポイントを正確に特定することができたので、私の質問はコード自体ではなく、クエリを高速化するための他の代替手段についてです。 したがって、取得されるデータは、複数の「メンバーシップ」と「ユーザー」を含む「サイト」データです。したがって、問題は、クエリがユーザー情報をサイトに接続しようとすると、実行が遅くなるということです。次のようになります:</p> <pre class="brush:php;toolbar:false;">$qb->leftJoin('s.memberships', 'ex_sm', 'WITH', 'ex_sm.revokedAt IS NULL'); $qb->leftJoin('ex_sm.user', 'ex_jappr', 'WITH', 'ex_sm.approverJobReactiveWeight IS NOT NULL');</pre> <p>いくつか言及すべきこと (私が試したこと、または役に立つかもしれないと思ったこと): </p>
    <li>テーブルを確認したところ、リンクされているすべての列にはインデックスがあり、それらはすべて同じ int データ型です。 </li> <li>DQL のパフォーマンスの問題に関する記事を書きました。その記事では、DQL Left Join 呼び出しを使いすぎると、同じエンティティ オブジェクトが何度も再マップされるため、パフォーマンスが低下する可能性があると述べられていました。考えられる解決策の 1 つは、メイン データセットを取得し、フィールドのエンティティ クラスから直接各要素に追加 (接続されたデータ フィールド) を追加してコレクションをループすることです。これは機能するかもしれません (どの程度の影響があるかはわかりません)。問題は、私が持っているのは非常に複雑な従来のコードであり、あまりにも多くのテストが必要になるため、エクスポートマネージャーのロジックには触れたくないことです。エクスポート マネージャーにはクエリ ビルダー クラスが必要なので、クエリ自体で解決策を見つける必要があります。 </li> <li>この問題は、WITH 句や追加の条件ではなく、明らかに結合によって発生します。通常の leftJoin 呼び出しを使用してクエリを呼び出してみましたが、同じ結果が得られました。 </li> <li>leftJoin メソッドの呼び出しは相互に連鎖できることはわかっています。呼び出しの一部が if ステートメントで使用されているため、コードは次のようになります。 </li> <li>私は 2 日間かけて、ここや他のサイトで見つけたものすべてを試しました。 </li> </ul> <p>6 つの異なるユーザー タイプがあります。ここでは、スクリプトを呼び出して上記のユーザー タイプを取得するだけで、データを返すのに 33 分かかりました。これは 512 のサイトについて話していますが、これは膨大なデータのコレクションではありません。そこで私の質問は次のとおりです。このような複雑なクエリでの leftJoins の呼び出し数を簡素化または削減し、何らかの方法でパフォーマンスを向上させる別の DQL または Doctrine の方法はありますか? </p> <p>更新: 問題はインデックスにあると考えたので、その関係についていくつか詳しく説明しました。 「memberships」エンティティは「access」という名前のテーブルから取得され、そのモデル内のユーザーとの関係は次のとおりです。 <pre class="brush:php;toolbar:false;">/*** このメンバーシップがカプセル化するユーザー。 * * @ORM\ManyToOne(targetEntity="User", inversedBy="siteMemberships", cascade={"persist"}) * @ORM\JoinColumn(name="security_identity_id"、referencedColumnName="id") * * @var ユーザー*/ protected $user;</pre> <p>これは、「security_identity_id」列に割り当てられたインデックスのスクリーンショットです。 </p> <p>関連ユーザーは、メンバーシップを指す関係を持つ Users テーブルから取得されます</p> <pre class="brush:php;toolbar:false;">/*** @ORM\OneToMany(targetEntity="SiteMembership"、mappedBy="user"、cascade={"persist"}、fetch="EXTRA_LAZY")*/ protected $siteMemberships;</pre> <p>主キーはエンティティ内の「id」です。これにより、物事がより良い視点で捉えられるようになることを願っています。私は SQL の専門家ではありませんが、見つけたものはすべて試してみたので、これまでのところ理解できます。 </p> <p>更新: これは実行されたクエリです: </p> <pre class="brush:php;toolbar:false;">SELECT s0_.name AS name_0, s0_.id AS id_1, GROUP_CONCAT(DISTINCT u1_.name SEPARATOR ', ') AS sclr_2 FROM site s0_ LEFT JOIN アクセス a2_ ON s0_.id = a2_.entity_id AND a2_.type IN ('site_member') AND (a2_.revoked_at は NULL) LEFT JOIN ユーザー u1_ ON a2_.security_identity_id = u1_.id AND (a2_.approver_job_reactive_weight IS NOT NULL)</pre> <p>これにより、最初のサイト レコードがそのメンバーシップとユーザー権限とともに返されます。しかし、この列でも2分以上かかります。 </p> <p>(メンバエンティティ)テーブルにアクセスするためのテーブル作成情報です</p> <pre class="brush:php;toolbar:false;">'CREATE TABLE `access` ( `id` int(11) NOT NULL AUTO_INCREMENT、 `buddy_id` int(11) デフォルト NULL、 `security_identity_id` int(11) デフォルト NULL、 `revoked_at` datetime DEFAULT NULL、 `created_at` 日時が NULL ではありません。 `updated_at` 日時が NULL ではありません。 `type` varchar(255) COLLATE utf8_unicode_ci NOT NULL、 `approver_job_reactive_weight` int(11) DEFAULT NULL, `entity_id` int(11) デフォルト NULL、 主キー (`id`)、 一意のキー `access_idx` (`type`、`security_identity_id`、`entity_id`、`buddy_id`)、 キー `IDX_6692B54395CE8D6` (`buddy_id`)、 KEY `IDX_6692B54DF9183C9` (`security_identity_id`)、 KEY `IDX_6692B5481257D5D` (`entity_id`)、 KEY `idx_revoked_id_approver_type` (`revoked_at`、`entity_id`、`approver_job_reactive_weight`、`approver_job_planned_weight`、`type`)、 KEY `idx_user_site_access` (`revoked_at`、`security_identity_id`、`buddy_id`、`type`)、 KEY `idx_user` (`security_identity_id`)、 KEY `idx_user_id` (`security_identity_id`)、 制約 `FK_6692B54DF9183C9` 外部キー (`security_identity_id`) 参照 `user` (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=262441 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci'</pre> <p>関係のない列をいくつか削除しました。 </p>
P粉517475670
P粉517475670

全員に返信(2)
P粉208286791

あなたはたくさんのキャンプに参加しました。それが速度が低下している理由です

リーリー

メンバーシップの数が増えると、クエリの速度が遅くなります。完全なクエリについてはわかりませんが、メンバーシップ テーブルからクエリを開始することも、2 番目のクエリを実行することもできます。

いいねを押す +0
P粉178894235

LEFT JOIN を実行する場合、ON はテーブルがどのように関連しているかを説明する必要があります。 WHERE 句には通常、右側の行を除外するか含めるかを示す IS NULL または IS NOT NULL が含まれます。

LEFT JOININNER JOIN の速度は基本的に同じです。ただし、インデックスの SQL (SHOW CREATE TABLE) と SELECT を調べて、他に問題があるかどうかを確認する必要があります。 ######もっと###### ###交換する### リーリー ###そして### リーリー

いいねを押す +0
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート