Penyelesaian yang mungkin untuk memperlahankan gabungan kiri dalam pertanyaan doktrin yang kompleks
P粉517475670
P粉517475670 2023-09-02 18:55:02
0
2
695
<p>Saya mempunyai kaedah repositori symfony yang mengambil set data yang agak kompleks yang kemudiannya diletakkan dalam fail CSV oleh kelas pengurus eksport. Saya tidak mahu meletakkan keseluruhan kod yang mengendalikan kerja eksport, tetapi saya berjaya menentukan titik di mana pertanyaan menjadi perlahan, jadi soalan saya adalah mengenai sebarang alternatif lain untuk membuat pertanyaan lebih pantas, dan bukannya kod itu sendiri. Jadi data yang diambil ialah beberapa data "tapak" yang mempunyai berbilang "Keahlian" dan kemudian mempunyai "Pengguna".Jadi masalahnya ialah apabila pertanyaan saya cuba menyambungkan maklumat pengguna ke tapak, ia memperlahankan pelaksanaan. Ia kelihatan seperti ini:</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>Beberapa perkara untuk disebutkan (yang saya cuba atau fikir mungkin membantu): </p> <ul> <li>Saya menyemak jadual dan semua lajur yang dipautkan mempunyai indeks dan kesemuanya adalah jenis data int yang sama. </li> <li>Saya reda artikel tentang isu prestasi DQL yang menyebut bahawa penggunaan berlebihan panggilan DQL Left Join boleh mengurangkan prestasi kerana ia memetakan semula objek entiti yang sama berulang kali. Satu penyelesaian yang mungkin disebut adalah untuk mendapatkan set data utama dan kemudian gelung melalui koleksi menambah lampiran (medan data yang disambungkan) kepada setiap elemen terus dari kelas entiti medan. Ini mungkin berfungsi (tidak pasti berapa banyak kesannya), masalahnya ialah apa yang saya ada ialah kod warisan yang sangat kompleks dan saya tidak mahu menyentuh logik pengurus eksport kerana itu memerlukan terlalu banyak ujian. Pengurus eksport memerlukan kelas pembina pertanyaan, jadi saya perlu mencari penyelesaian dalam pertanyaan itu sendiri. </li> <li>Masalahnya pasti disebabkan oleh gabungan, bukan klausa WITH atau syarat tambahan. Saya cuba memanggil pertanyaan menggunakan panggilan leftJoin biasa, dengan keputusan yang sama. </li> <li>Saya tahu bahawa panggilan kaedah leftJoin boleh dirantai antara satu sama lain, kodnya kelihatan seperti ini kerana beberapa panggilan digunakan dalam pernyataan if. </li> <li>Saya menghabiskan 2 hari mencuba semua yang saya temui di sini dan di tapak lain. </li> </ul> <p>Terdapat 6 jenis pengguna yang berbeza, kini saya hanya memanggil skrip untuk mendapatkan jenis pengguna di atas dan mengambil masa 33 minit untuk mengembalikan data. Kami bercakap tentang 512 tapak, yang bukan koleksi data yang besar.Jadi soalan saya ialah: Adakah terdapat DQL atau mana-mana cara Doktrin lain untuk memudahkan atau mengurangkan bilangan panggilan ke leftJoins dalam pertanyaan yang begitu kompleks dan entah bagaimana meningkatkan prestasi? </p> <p>Kemas kini: Saya fikir masalahnya adalah dengan indeks, jadi saya memberikan beberapa butiran tentang hubungan itu: Entiti "keahlian" berasal daripada jadual bernama "akses" dan hubungan dengan pengguna dalam modelnya adalah seperti berikut: </p> <pre class="brush:php;toolbar:false;">/*** Pengguna yang dirangkumkan oleh keahlian ini. * * @ORMManyToOne(targetEntity="User", inversedBy="siteMemberships", cascade={"berterusan"}) * @ORMJoinColumn(name="security_identity_id", referencedColumnName="id") * * Pengguna @var*/ dilindungi $user;</pre> <p>Ini ialah tangkapan skrin indeks yang diberikan kepada lajur "id_identiti_keselamatan" </p> <p>Pengguna berkaitan datang dari jadual Pengguna dengan perhubungan yang menunjuk kepada keahlian</p> <pre class="brush:php;toolbar:false;">/*** @ORMOneToMany(targetEntity="SiteMembership", mappedBy="user", cascade={"berterusan"}, fetch="EXTRA_LAZY")*/ dilindungi $siteMemberships;</pre> <p>Kunci utama ialah "id" dalam entiti.Harap ini meletakkan perkara ke dalam perspektif yang lebih baik. Saya bukan pakar sql tetapi telah mencuba semua yang saya temui dan boleh memikirkannya setakat ini. </p> <p>Kemas kini: Ini ialah pertanyaan yang dilaksanakan: </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 DARIPADA tapak s0_ KIRI SERTAI akses a2_ HIDUP s0_.id = a2_.id_entiti DAN a2_.type IN ('ahli_tapak') DAN (a2_.revoked_at IS NULL) KIRI SERTAI pengguna u1_ PADA a2_.security_identity_id = u1_.id DAN (a2_.approver_job_reactive_weight BUKAN NULL)</pre> <p>Ini akan mengembalikan rekod tapak pertama bersama dengan keahliannya dan kebenaran pengguna. Tetapi barisan ini pun mengambil masa lebih 2 minit. </p> <p>Berikut ialah maklumat penciptaan jadual untuk mengakses jadual (entiti ahli)</p> <pre class="brush:php;toolbar:false;">'BUAT JADUAL `akses` ( `id` int(11) BUKAN NULL AUTO_INCREMENT, `buddy_id` int(11) DEFAULT NULL, `id_identiti_keselamatan` int(11) LALAI NULL, `dibatalkan_pada` tarikh masa lalai NULL, `dicipta_pada` tarikh masa BUKAN NULL, `updated_at` datetime NOT NULL, `type` varchar(255) COLLATE utf8_unicode_ci NOT NULL, `pelulus_pekerjaan_berat_reaktif` int(11) LALAI NULL, `id_entiti` int(11) LALAI NULL, KUNCI UTAMA (`id`), KUNCI UNIK `access_idx` (`type`,`security_identity_id`,`entity_id`,`buddy_id`), KUNCI `IDX_6692B54395CE8D6` (`buddy_id`), KUNCI `IDX_6692B54DF9183C9` (`id_identiti_keselamatan`), KUNCI `IDX_6692B5481257D5D` (`id_entiti`), 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`), KUNCI `idx_user_id` (`security_identity_id`), KEKANGAN `FK_6692B54DF9183C9` KUNCI ASING (`id_identiti_keselamatan`) RUJUKAN `pengguna` (`id`) ) ENJIN=InnoDB AUTO_INCREMENT=262441 CARSET LALAI=utf8 COLLATE=utf8_unicode_ci'</pre> <p>Saya memadamkan beberapa lajur yang tidak berkaitan. </p>
P粉517475670
P粉517475670

membalas semua(2)
P粉208286791

Anda menyertai banyak kem. Itulah sebabnya ia perlahan

$qb->leftJoin('s.memberships', 'ex_sm', 'WITH', 'ex_sm.revokedAt IS NULL');

Semakin banyak keahlian anda, semakin perlahan kelajuan pertanyaan. Saya tidak tahu tentang pertanyaan penuh, tetapi anda boleh memulakan pertanyaan daripada jadual keahlian atau melakukan pertanyaan kedua.

P粉178894235

Apabila selesai LEFT JOIN时,ON需要说明表是如何关联的。 WHERE 子句通常有 IS NULLIS NOT NULL menunjukkan sama ada untuk mengecualikan atau memasukkan baris kanan.

LEFT JOININNER JOIN 的速度基本相同。但我需要查看索引 (SHOW CREATE TABLE) 和 SELECT SQL untuk melihat jika terdapat isu lain.

Lagi

Pengganti

KEY `IDX_6692B5481257D5D` (`entity_id`),

dan

INDEX(entity_id, type, revoked_at)
Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan