Uploaded image for project: 'MariaDB Server'
  1. MariaDB Server
  2. MDEV-41532

Exponential time of the second execution of PS/SP with nested derived tables or views

    XMLWordPrintable

Details

    Description

      Re-executing a prepared statement or a stored procedure statement that has nested derived tables or views takes exponential time in the nesting depth. Each level doubles the time. Direct execution, PREPARE and the first EXECUTE are fast. The derived tables need no expressions, a chain that only passes a column through is enough.

      Test case (mysqltest)

      create table t1 (f1 int);
      insert into t1 values (1),(2);
       
      --disable_query_log
      let $levels= 30;
      let $q= select f1 as s1 from t1;
      let $i= 1;
      while ($i < $levels)
      {
        let $j= $i;
        inc $j;
        let $q= select s$i as s$j from ($q) dt$i;
        inc $i;
      }
      --echo # direct execution: fast
      eval $q;
      eval prepare stmt from "$q";
      --enable_query_log
      --echo # first execution: fast
      execute stmt;
      --echo # second execution: exponential in the nesting depth
      execute stmt;
      deallocate prepare stmt;
       
      --disable_query_log
      eval create procedure p() $q;
      --enable_query_log
      call p();
      --echo # second call: exponential as well
      call p();
      drop procedure p;
       
      drop table t1;

      Test case (plain SQL)

      create table t1 (f1 int);
      insert into t1 values (1),(2);
      prepare stmt from 'select s29 as s30 from (select s28 as s29 from (select s27 as s28 from (select s26 as s27 from (select s25 as s26 from (select s24 as s25 from (select s23 as s24 from (select s22 as s23 from (select s21 as s22 from (select s20 as s21 from (select s19 as s20 from (select s18 as s19 from (select s17 as s18 from (select s16 as s17 from (select s15 as s16 from (select s14 as s15 from (select s13 as s14 from (select s12 as s13 from (select s11 as s12 from (select s10 as s11 from (select s9 as s10 from (select s8 as s9 from (select s7 as s8 from (select s6 as s7 from (select s5 as s6 from (select s4 as s5 from (select s3 as s4 from (select s2 as s3 from (select s1 as s2 from (select f1 as s1 from t1) dt1) dt2) dt3) dt4) dt5) dt6) dt7) dt8) dt9) dt10) dt11) dt12) dt13) dt14) dt15) dt16) dt17) dt18) dt19) dt20) dt21) dt22) dt23) dt24) dt25) dt26) dt27) dt28) dt29';
      execute stmt;  -- fast
      execute stmt;  -- 6 s, doubles with each extra level

      Timings

      10.11 (bf6311c49ec), RelWithDebInfo build, 2 rows:

      depth direct PREPARE 1st EXECUTE 2nd EXECUTE (derived) 2nd EXECUTE (views v_i = select from v_(i-1))
      20 <1 ms <1 ms <1 ms 8 ms 13 ms
      24 <1 ms 1 ms <1 ms 108 ms 194 ms
      28 <1 ms 1 ms 1 ms 1486 ms 2690 ms
      30 <1 ms 1 ms 1 ms 6007 ms 11579 ms

      A stored procedure behaves the same: with depth 26 every first CALL in a connection takes 4-6 ms, and the second CALL in the same connection takes about 400 ms.

      Where the time goes

      The second EXECUTE spends the time in recursive derived table handling during JOIN::prepare:

      mysql_derived_prepare
      mysql_handle_single_derived
      TABLE_LIST::handle_derived
      LEX::handle_list_of_derived
      st_select_lex::handle_derived
      mysql_derived_prepare
      mysql_handle_single_derived
      TABLE_LIST::handle_derived
      ... (repeats for every nesting level)
      st_select_lex::handle_derived
      JOIN::prepare
      mysql_select
      handle_select
      execute_sqlcom_select
      mysql_execute_command
      Prepared_statement::execute

      A guess, not verified: TABLE_LIST::handle_derived() first recurses into the selects of the inner unit, and then mysql_handle_single_derived() -> mysql_derived_prepare() -> JOIN::prepare() of the same unit handles the derived tables of those selects again. That makes two recursive calls per level. On the first execution the inner units are already merged or marked prepared, so the repeated subtree is skipped.

      Found while working on MDEV-31130: under --ps-protocol, its test with 40 levels hung in this code and not in the MDEV-31130 code.

      Attachments

        Issue Links

          Activity

            People

              sanja Oleksandr Byelkin
              sanja Oleksandr Byelkin
              Votes:
              0 Vote for this issue
              Watchers:
              1 Start watching this issue

              Dates

                Created:
                Updated:

                Git Integration

                  Error rendering 'com.xiplink.jira.git.jira_git_plugin:git-issue-webpanel'. Please contact your Jira administrators.