<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>
あなたはたくさんのキャンプに参加しました。それが速度が低下している理由です
リーリーメンバーシップの数が増えると、クエリの速度が遅くなります。完全なクエリについてはわかりませんが、メンバーシップ テーブルからクエリを開始することも、2 番目のクエリを実行することもできます。
LEFT JOIN
を実行する場合、
ONはテーブルがどのように関連しているかを説明する必要があります。
WHERE句には通常、右側の行を除外するか含めるかを示す
IS NULLまたは
IS NOT NULLが含まれます。
LEFT JOIN
と
INNER JOINの速度は基本的に同じです。ただし、インデックスの SQL (
SHOW CREATE TABLE) と
SELECTを調べて、他に問題があるかどうかを確認する必要があります。
######もっと###### ###交換する### リーリー ###そして### リーリー