Uploaded image for project: 'Moodle'
  1. Moodle
  2. MDL-18587

Performance of get_user_access_sitewide is unnecessarily poor

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Duplicate
    • Icon: Minor Minor
    • None
    • 1.9.4
    • Roles / Access
    • None
    • PostgreSQL
    • MOODLE_19_STABLE

      get_user_access_sitewide performs poorly when the context table is large. This affects Postgres for sure and may possibly affect other databases.

      The cause is this query:

      $sql = "SELECT sctx.path, ra.roleid,
      ctx.path AS parentpath,
      rco.capability, rco.permission
      FROM {$CFG->prefix}role_assignments ra
      JOIN {$CFG->prefix}context ctx
      ON ra.contextid=ctx.id
      JOIN {$CFG->prefix}context sctx
      ON (sctx.path LIKE " . sql_concat('ctx.path',"'/%'"). " )
      JOIN {$CFG->prefix}role_capabilities rco
      ON (rco.roleid=ra.roleid AND rco.contextid=sctx.id)
      WHERE ra.userid = $userid
      AND sctx.contextlevel <= ".CONTEXT_COURSE."
      ORDER BY sctx.depth, sctx.path, ra.roleid";

      The join on context path is slow because the database is unable to use an index for LIKE followed by computed value. (Provided that you have added a Postgres pattern index, or the database is set to no locale, then the same LIKE would be perfectly fine if you just did LIKE '/1/23/1241241/%' or whatever, it's the computed bit that throws it.)

      This query is trying to find all subcontexts (sctx) of a main context where user has a role (ctx) that are of level course, category, or site. Courses cannot have subcontexts that meet this requirement. Most users roles on most sites are in courses. Therefore it is possible to dramatically improve performance by adding the following to the WHERE clause:

      AND ctx.contextlevel < CONTEXT_COURSE

      note < not <=: that means we only consider category, site level roles.

      This improves performance by a large factor in the typical student case (a few roles on a few courses); on our test server with no load it goes from 600ms to 15ms. It makes no difference in the admin/site level role case.

      Anything wrong with this assumption? Could somebody knowledgeable about roles confirm it? This fix should be applied to 1.9 if it is correct as it can save a second from each student login on a large system, which is a lot...

            stronk7 Eloy Lafuente (stronk7)
            quen Sam Marshall
            Votes:
            0 Vote for this issue
            Watchers:
            3 Start watching this issue

              Created:
              Updated:
              Resolved:

                Error rendering 'clockify-timesheets-time-tracking-reports:timer-sidebar'. Please contact your Jira administrators.