Skip to content

Conversation

@provokateurin
Copy link
Member

I tested this with the Contacts app and there showing the members still works without these LEFT JOINs as the requested data is never used.
This drastically reduces the number of LEFT JOINs from 13 to just 3.

Before:

SELECT "c"."circle_id",
       "c"."member_id",
       "c"."single_id",
       "c"."user_id",
       "c"."instance",
       "c"."user_type",
       "c"."level",
       "c"."status",
       "c"."note",
       "c"."contact_id",
       "c"."cached_name",
       "c"."cached_update",
       "c"."contact_meta",
       "c"."joined",
       "c_g"."unique_id"               AS "c_g_unique_id",
       "c_g"."name"                    AS "c_g_name",
       "c_g"."display_name"            AS "c_g_display_name",
       "c_g"."sanitized_name"          AS "c_g_sanitized_name",
       "c_g"."source"                  AS "c_g_source",
       "c_g"."description"             AS "c_g_description",
       "c_g"."settings"                AS "c_g_settings",
       "c_g"."config"                  AS "c_g_config",
       "c_g"."contact_addressbook"     AS "c_g_contact_addressbook",
       "c_g"."contact_groupname"       AS "c_g_contact_groupname",
       "c_g"."creation"                AS "c_g_creation",
       "c_g_d"."circle_id"             AS "c_g_d_circle_id",
       "c_g_d"."member_id"             AS "c_g_d_member_id",
       "c_g_d"."single_id"             AS "c_g_d_single_id",
       "c_g_d"."user_id"               AS "c_g_d_user_id",
       "c_g_d"."instance"              AS "c_g_d_instance",
       "c_g_d"."user_type"             AS "c_g_d_user_type",
       "c_g_d"."level"                 AS "c_g_d_level",
       "c_g_d"."status"                AS "c_g_d_status",
       "c_g_d"."note"                  AS "c_g_d_note",
       "c_g_d"."contact_id"            AS "c_g_d_contact_id",
       "c_g_d"."cached_name"           AS "c_g_d_cached_name",
       "c_g_d"."cached_update"         AS "c_g_d_cached_update",
       "c_g_d"."contact_meta"          AS "c_g_d_contact_meta",
       "c_g_d"."joined"                AS "c_g_d_joined",
       "c_b"."unique_id"               AS "c_b_unique_id",
       "c_b"."name"                    AS "c_b_name",
       "c_b"."display_name"            AS "c_b_display_name",
       "c_b"."sanitized_name"          AS "c_b_sanitized_name",
       "c_b"."source"                  AS "c_b_source",
       "c_b"."description"             AS "c_b_description",
       "c_b"."settings"                AS "c_b_settings",
       "c_b"."config"                  AS "c_b_config",
       "c_b"."contact_addressbook"     AS "c_b_contact_addressbook",
       "c_b"."contact_groupname"       AS "c_b_contact_groupname",
       "c_b"."creation"                AS "c_b_creation",
       "c_b_i"."circle_id"             AS "c_b_i_circle_id",
       "c_b_i"."member_id"             AS "c_b_i_member_id",
       "c_b_i"."single_id"             AS "c_b_i_single_id",
       "c_b_i"."user_id"               AS "c_b_i_user_id",
       "c_b_i"."instance"              AS "c_b_i_instance",
       "c_b_i"."user_type"             AS "c_b_i_user_type",
       "c_b_i"."level"                 AS "c_b_i_level",
       "c_b_i"."status"                AS "c_b_i_status",
       "c_b_i"."note"                  AS "c_b_i_note",
       "c_b_i"."contact_id"            AS "c_b_i_contact_id",
       "c_b_i"."cached_name"           AS "c_b_i_cached_name",
       "c_b_i"."cached_update"         AS "c_b_i_cached_update",
       "c_b_i"."contact_meta"          AS "c_b_i_contact_meta",
       "c_b_i"."joined"                AS "c_b_i_joined",
       "c_b_h"."circle_id"             AS "c_b_h_circle_id",
       "c_b_h"."member_id"             AS "c_b_h_member_id",
       "c_b_h"."single_id"             AS "c_b_h_single_id",
       "c_b_h"."user_id"               AS "c_b_h_user_id",
       "c_b_h"."instance"              AS "c_b_h_instance",
       "c_b_h"."user_type"             AS "c_b_h_user_type",
       "c_b_h"."level"                 AS "c_b_h_level",
       "c_b_h"."status"                AS "c_b_h_status",
       "c_b_h"."note"                  AS "c_b_h_note",
       "c_b_h"."contact_id"            AS "c_b_h_contact_id",
       "c_b_h"."cached_name"           AS "c_b_h_cached_name",
       "c_b_h"."cached_update"         AS "c_b_h_cached_update",
       "c_b_h"."contact_meta"          AS "c_b_h_contact_meta",
       "c_b_h"."joined"                AS "c_b_h_joined",
       "c_b_h_n"."circle_id"           AS "c_b_h_n_circle_id",
       "c_b_h_n"."member_id"           AS "c_b_h_n_member_id",
       "c_b_h_n"."single_id"           AS "c_b_h_n_single_id",
       "c_b_h_n"."user_id"             AS "c_b_h_n_user_id",
       "c_b_h_n"."instance"            AS "c_b_h_n_instance",
       "c_b_h_n"."user_type"           AS "c_b_h_n_user_type",
       "c_b_h_n"."level"               AS "c_b_h_n_level",
       "c_b_h_n"."status"              AS "c_b_h_n_status",
       "c_b_h_n"."note"                AS "c_b_h_n_note",
       "c_b_h_n"."contact_id"          AS "c_b_h_n_contact_id",
       "c_b_h_n"."cached_name"         AS "c_b_h_n_cached_name",
       "c_b_h_n"."cached_update"       AS "c_b_h_n_cached_update",
       "c_b_h_n"."contact_meta"        AS "c_b_h_n_contact_meta",
       "c_b_h_n"."joined"              AS "c_b_h_n_joined",
       "c_b_j"."single_id"             AS "c_b_h_n_j_single_id",
       "c_b_j"."circle_id"             AS "c_b_h_n_j_circle_id",
       "c_b_j"."level"                 AS "c_b_h_n_j_level",
       "c_b_j"."inheritance_first"     AS "c_b_h_n_j_inheritance_first",
       "c_b_j"."inheritance_last"      AS "c_b_h_n_j_inheritance_last",
       "c_b_j"."inheritance_path"      AS "c_b_h_n_j_inheritance_path",
       "c_b_j"."inheritance_depth"     AS "c_b_h_n_j_inheritance_depth",
       "c_b_h_g"."unique_id"           AS "c_b_h_g_unique_id",
       "c_b_h_g"."name"                AS "c_b_h_g_name",
       "c_b_h_g"."display_name"        AS "c_b_h_g_display_name",
       "c_b_h_g"."sanitized_name"      AS "c_b_h_g_sanitized_name",
       "c_b_h_g"."source"              AS "c_b_h_g_source",
       "c_b_h_g"."description"         AS "c_b_h_g_description",
       "c_b_h_g"."settings"            AS "c_b_h_g_settings",
       "c_b_h_g"."config"              AS "c_b_h_g_config",
       "c_b_h_g"."contact_addressbook" AS "c_b_h_g_contact_addressbook",
       "c_b_h_g"."contact_groupname"   AS "c_b_h_g_contact_groupname",
       "c_b_h_g"."creation"            AS "c_b_h_g_creation",
       "c_b_d"."circle_id"             AS "c_b_d_circle_id",
       "c_b_d"."member_id"             AS "c_b_d_member_id",
       "c_b_d"."single_id"             AS "c_b_d_single_id",
       "c_b_d"."user_id"               AS "c_b_d_user_id",
       "c_b_d"."instance"              AS "c_b_d_instance",
       "c_b_d"."user_type"             AS "c_b_d_user_type",
       "c_b_d"."level"                 AS "c_b_d_level",
       "c_b_d"."status"                AS "c_b_d_status",
       "c_b_d"."note"                  AS "c_b_d_note",
       "c_b_d"."contact_id"            AS "c_b_d_contact_id",
       "c_b_d"."cached_name"           AS "c_b_d_cached_name",
       "c_b_d"."cached_update"         AS "c_b_d_cached_update",
       "c_b_d"."contact_meta"          AS "c_b_d_contact_meta",
       "c_b_d"."joined"                AS "c_b_d_joined",
       "c_o"."unique_id"               AS "c_o_unique_id",
       "c_o"."name"                    AS "c_o_name",
       "c_o"."display_name"            AS "c_o_display_name",
       "c_o"."sanitized_name"          AS "c_o_sanitized_name",
       "c_o"."source"                  AS "c_o_source",
       "c_o"."description"             AS "c_o_description",
       "c_o"."settings"                AS "c_o_settings",
       "c_o"."config"                  AS "c_o_config",
       "c_o"."contact_addressbook"     AS "c_o_contact_addressbook",
       "c_o"."contact_groupname"       AS "c_o_contact_groupname",
       "c_o"."creation"                AS "c_o_creation",
       "c_o_d"."circle_id"             AS "c_o_d_circle_id",
       "c_o_d"."member_id"             AS "c_o_d_member_id",
       "c_o_d"."single_id"             AS "c_o_d_single_id",
       "c_o_d"."user_id"               AS "c_o_d_user_id",
       "c_o_d"."instance"              AS "c_o_d_instance",
       "c_o_d"."user_type"             AS "c_o_d_user_type",
       "c_o_d"."level"                 AS "c_o_d_level",
       "c_o_d"."status"                AS "c_o_d_status",
       "c_o_d"."note"                  AS "c_o_d_note",
       "c_o_d"."contact_id"            AS "c_o_d_contact_id",
       "c_o_d"."cached_name"           AS "c_o_d_cached_name",
       "c_o_d"."cached_update"         AS "c_o_d_cached_update",
       "c_o_d"."contact_meta"          AS "c_o_d_contact_meta",
       "c_o_d"."joined"                AS "c_o_d_joined"
FROM "oc_circles_member" "c"
         LEFT JOIN "oc_circles_circle" "c_g" ON "c_g"."unique_id" = "c"."single_id"
         LEFT JOIN "oc_circles_circle" "c_b" ON "c_b"."unique_id" = "c"."circle_id"
         LEFT JOIN "oc_circles_circle" "c_o" ON "c"."invited_by" = "c_o"."unique_id"
         LEFT JOIN "oc_circles_membership" "c_g_j"
                   ON ("c_g_j"."single_id" = $1) AND ("c_g_j"."circle_id" = "c_g"."unique_id")
         LEFT JOIN "oc_circles_member" "c_g_d" ON ("c_g_d"."circle_id" = "c_g"."unique_id") AND ("c_g_d"."level" = $2)
         LEFT JOIN "oc_circles_membership" "c_b_j"
                   ON ("c_b_j"."single_id" = $3) AND ("c_b_j"."circle_id" = "c_b"."unique_id")
         LEFT JOIN "oc_circles_member" "c_b_i"
                   ON ("c_b_i"."single_id" = $4) AND ("c_b_i"."circle_id" = "c_b"."unique_id")
         LEFT JOIN "oc_circles_member" "c_b_d" ON ("c_b_d"."circle_id" = "c_b"."unique_id") AND ("c_b_d"."level" = $5)
         LEFT JOIN "oc_circles_circle" "c_b_j_k"
                   ON ("c_b_j"."circle_id" = "c_b_j_k"."unique_id") OR ("c_b_i"."circle_id" = "c_b_j_k"."unique_id")
         LEFT JOIN "oc_circles_member" "c_b_h" ON ("c_b_j"."inheritance_first" = "c_b_h"."single_id") AND
                                                  ("c_b_j"."circle_id" = "c_b_h"."circle_id")
         LEFT JOIN "oc_circles_member" "c_b_h_n" ON ("c_b_j"."single_id" = "c_b_h_n"."single_id") AND
                                                    ("c_b_j"."inheritance_last" = "c_b_h_n"."circle_id")
         LEFT JOIN "oc_circles_circle" "c_b_h_g" ON "c_b_h_g"."unique_id" = "c_b_h"."single_id"
         LEFT JOIN "oc_circles_member" "c_o_d" ON ("c_o_d"."circle_id" = "c_o"."unique_id") AND ("c_o_d"."level" = $6)
WHERE ("c"."circle_id" = $7)
  AND (((("c_b_j_k"."config" & 2) > $8) AND ("c_b_j"."level" = $9)) OR
       ((("c_b_j"."level" >= $10) OR ("c_b_i"."level" >= $11)) AND (("c_b_j_k"."config" & 2) = $12)) OR
       ((("c_b"."config" & 16) > $13) AND (("c_b"."config" & 8) > $14) AND (("c_b"."config" & 64) = $15)))
ORDER BY "c"."level" desc, "c"."cached_name" asc

After:

SELECT "c"."circle_id",
       "c"."member_id",
       "c"."single_id",
       "c"."user_id",
       "c"."instance",
       "c"."user_type",
       "c"."level",
       "c"."status",
       "c"."note",
       "c"."contact_id",
       "c"."cached_name",
       "c"."cached_update",
       "c"."contact_meta",
       "c"."joined",
       "c_g"."unique_id"           AS "c_g_unique_id",
       "c_g"."name"                AS "c_g_name",
       "c_g"."display_name"        AS "c_g_display_name",
       "c_g"."sanitized_name"      AS "c_g_sanitized_name",
       "c_g"."source"              AS "c_g_source",
       "c_g"."description"         AS "c_g_description",
       "c_g"."settings"            AS "c_g_settings",
       "c_g"."config"              AS "c_g_config",
       "c_g"."contact_addressbook" AS "c_g_contact_addressbook",
       "c_g"."contact_groupname"   AS "c_g_contact_groupname",
       "c_g"."creation"            AS "c_g_creation",
       "c_g_d"."circle_id"         AS "c_g_d_circle_id",
       "c_g_d"."member_id"         AS "c_g_d_member_id",
       "c_g_d"."single_id"         AS "c_g_d_single_id",
       "c_g_d"."user_id"           AS "c_g_d_user_id",
       "c_g_d"."instance"          AS "c_g_d_instance",
       "c_g_d"."user_type"         AS "c_g_d_user_type",
       "c_g_d"."level"             AS "c_g_d_level",
       "c_g_d"."status"            AS "c_g_d_status",
       "c_g_d"."note"              AS "c_g_d_note",
       "c_g_d"."contact_id"        AS "c_g_d_contact_id",
       "c_g_d"."cached_name"       AS "c_g_d_cached_name",
       "c_g_d"."cached_update"     AS "c_g_d_cached_update",
       "c_g_d"."contact_meta"      AS "c_g_d_contact_meta",
       "c_g_d"."joined"            AS "c_g_d_joined"
FROM "oc_circles_member" "c"
         LEFT JOIN "oc_circles_circle" "c_g" ON "c_g"."unique_id" = "c"."single_id"
         LEFT JOIN "oc_circles_membership" "c_g_j"
                   ON ("c_g_j"."single_id" = $1) AND ("c_g_j"."circle_id" = "c_g"."unique_id")
         LEFT JOIN "oc_circles_member" "c_g_d" ON ("c_g_d"."circle_id" = "c_g"."unique_id") AND ("c_g_d"."level" = $2)
WHERE "c"."circle_id" = $3
ORDER BY "c"."level" desc, "c"."cached_name" asc

@provokateurin provokateurin added this to the Nextcloud 32 milestone Apr 14, 2025
@provokateurin provokateurin force-pushed the perf/memberrequest/remove-unused-left-joins branch from f081ecb to b754c91 Compare April 14, 2025 08:08
@provokateurin provokateurin force-pushed the perf/memberrequest/remove-unused-left-joins branch from 1d8c2ef to f63b1fd Compare June 2, 2025 11:10
@provokateurin provokateurin enabled auto-merge June 2, 2025 11:10
@provokateurin provokateurin merged commit 312fb93 into master Jun 2, 2025
31 checks passed
@provokateurin provokateurin deleted the perf/memberrequest/remove-unused-left-joins branch June 2, 2025 11:22
@provokateurin
Copy link
Member Author

/backport to stable31

@provokateurin
Copy link
Member Author

/backport to stable30

@provokateurin
Copy link
Member Author

/backport to stable29

mejo- added a commit that referenced this pull request Jun 4, 2025
PR #1969 broke members management in Collectives.

Collectives needs the initiator of a request to check if the current
user is an (inherited) member of non-user members (like circles and
groups).

Signed-off-by: Jonas <[email protected]>
backportbot bot pushed a commit that referenced this pull request Jun 4, 2025
PR #1969 broke members management in Collectives.

Collectives needs the initiator of a request to check if the current
user is an (inherited) member of non-user members (like circles and
groups).

Signed-off-by: Jonas <[email protected]>
backportbot bot pushed a commit that referenced this pull request Jun 4, 2025
PR #1969 broke members management in Collectives.

Collectives needs the initiator of a request to check if the current
user is an (inherited) member of non-user members (like circles and
groups).

Signed-off-by: Jonas <[email protected]>
backportbot bot pushed a commit that referenced this pull request Jun 4, 2025
PR #1969 broke members management in Collectives.

Collectives needs the initiator of a request to check if the current
user is an (inherited) member of non-user members (like circles and
groups).

Signed-off-by: Jonas <[email protected]>
@skjnldsv skjnldsv modified the milestones: Nextcloud 32, Nextcloud 33 Sep 28, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants