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:
$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');
Beberapa perkara untuk disebutkan (yang saya cuba atau fikir mungkin membantu):
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?
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:
/*** Pengguna yang dirangkumkan oleh keahlian ini. * * @ORMManyToOne(targetEntity="User", inversedBy="siteMemberships", cascade={"berterusan"}) * @ORMJoinColumn(name="security_identity_id", referencedColumnName="id") * * Pengguna @var*/ dilindungi $user;
Ini ialah tangkapan skrin indeks yang diberikan kepada lajur "id_identiti_keselamatan"
Pengguna berkaitan datang dari jadual Pengguna dengan perhubungan yang menunjuk kepada keahlian
/*** @ORMOneToMany(targetEntity="SiteMembership", mappedBy="user", cascade={"berterusan"}, fetch="EXTRA_LAZY")*/ dilindungi $siteMemberships;
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.
Kemas kini: Ini ialah pertanyaan yang dilaksanakan:
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)
Ini akan mengembalikan rekod tapak pertama bersama dengan keahliannya dan kebenaran pengguna. Tetapi barisan ini pun mengambil masa lebih 2 minit.
Berikut ialah maklumat penciptaan jadual untuk mengakses jadual (entiti ahli)
'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'
Saya memadamkan beberapa lajur yang tidak berkaitan.
Anda menyertai banyak kem. Itulah sebabnya ia perlahan
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.
Apabila selesai
LEFT JOIN
时,ON
需要说明表是如何关联的。WHERE
子句通常有IS NULL
或IS NOT NULL
menunjukkan sama ada untuk mengecualikan atau memasukkan baris kanan.LEFT JOIN
和INNER JOIN
的速度基本相同。但我需要查看索引 (SHOW CREATE TABLE
) 和SELECT
SQL untuk melihat jika terdapat isu lain.Lagi
Pengganti
dan