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

Assertion `0 < sel && sel <= 2.0' failed in table_cond_selectivity

Details

    • Bug
    • Status: Stalled (View Workflow)
    • Major
    • Resolution: Unresolved
    • 10.1(EOL), 10.2(EOL), 10.3(EOL), 10.4(EOL)
    • 10.11
    • Optimizer
    • None

    Description

      I see 10.1 crashing after MDEV-20576 is pused to 10.1

      Here is the stack trace

      #5  0x00007ffff5284412 in __GI___assert_fail (assertion=0x555557773960 "0 < sel && sel <= 2.0", 
          file=0x555557772de0 "/home/varunraiko/MariaDB/10.1-dev/sql/sql_select.cc", line=7764, 
          function=0x55555777be40 <table_cond_selectivity(JOIN*, unsigned int, st_join_table*, unsigned long long)::__PRETTY_FUNCTION__> "double table_cond_selectivity(JOIN*, uint, JOIN_TAB*, table_map)") at assert.c:101
      #6  0x00005555560069bc in table_cond_selectivity (join=<optimized out>, idx=<optimized out>, s=<optimized out>, rem_tables=0)
          at /home/varunraiko/MariaDB/10.1-dev/sql/sql_select.cc:7764
      #7  0x000055555602bc3a in best_extension_by_limited_search (join=0x62b000010230, remaining_tables=2, idx=<optimized out>, 
          record_count=<optimized out>, read_time=<optimized out>, search_depth=<optimized out>, prune_level=<optimized out>, 
          use_cond_selectivity=<optimized out>) at /home/varunraiko/MariaDB/10.1-dev/sql/sql_select.cc:8022
      #8  0x000055555602d7c1 in greedy_search (use_cond_selectivity=2, prune_level=1, search_depth=62, remaining_tables=2, 
          join=0x62b000010230) at /home/varunraiko/MariaDB/10.1-dev/sql/sql_select.cc:7169
      #9  choose_plan (join=0x62b000010230, join_tables=<optimized out>) at /home/varunraiko/MariaDB/10.1-dev/sql/sql_select.cc:6745
      #10 0x0000555556090973 in make_join_statistics (join=<optimized out>, tables_list=..., keyuse_array=<optimized out>)
          at /home/varunraiko/MariaDB/10.1-dev/sql/sql_select.cc:4249
      #11 0x00005555560ab39c in JOIN::optimize_inner (this=0x62b000010230) at /home/varunraiko/MariaDB/10.1-dev/sql/sql_select.cc:1405
      #12 0x00005555560b61e4 in JOIN::optimize (this=0x62b000010230) at /home/varunraiko/MariaDB/10.1-dev/sql/sql_select.cc:1059
      

      This crash is reproducible with the below mtr test :

      --source include/have_sequence.inc
       
      create table t1 (id int, a int, PRIMARY KEY(id), key(a));
      insert into t1 select seq,seq from seq_1_to_100;
      create table t2 (id int, a int, b int, PRIMARY KEY(id), key(a), key(b));
      insert into t2 select seq,seq,seq from seq_1_to_100;
       
      set optimizer_use_condition_selectivity=2;
      EXPLAIN  SELECT * FROM t1 A, t1 B WHERE A.a = B.a and A.id = 65;
      

      Attachments

        Issue Links

          Activity

            varun Varun Gupta (Inactive) added a comment - - edited

            ANALYSIS

            Looking at the test case in the description:

            The WHERE clause is A.a = B.a AND A.id=65

            There is a primary key on A.id, so we will only read one table, hence so A is a const table.
            Then we substitute the value of A.a read from the const table
            in the condition A.a = B.a, so the condition now becomes B.a = 65.

            So the join planner picked ref access for table B
            The key is on column B.a

            (gdb) p table->alias.Ptr
            $11 = 0x7fffe00127e0 "B"
            (gdb) p table->cond_selectivity
            $9 = 0.01
            (gdb) p pos->key
            $14 = (KEYUSE *) 0x7fffe000aa30
            (gdb) p pos->key->key
            $15 = 1
            (gdb) p table->quick_keys.is_set(key)
            $12 = true
            (gdb) p table->quick_rows[key]
            $13 = 1
            

            Discount the seletivity for ref(const).

            sel /= (double)table->quick_rows[key] / (double) table->stat_records();
            

            After discount, we have

            (gdb) p sel
            $16 = 1
            

            Discount selectivity for ref(non-const)

            Here we again consider the case B.a = A.a

            (gdb) p next_field->table->alias.Ptr
            $26 = 0x7fffe00126c0 "A"
            (gdb) p next_field->field_name
            $27 = 0x7fffe001055c "a"
            (gdb) p field->field_name
            $30 = 0x7fffe001055c "a"
            (gdb) p field->table->alias.Ptr
            $31 = 0x7fffe00127e0 "B"
            (gdb) p sel
            $28 = 1
            (gdb) p field->cond_selectivity
            $33 = 0.01
            

            So here the discount happens

            sel/= field->cond_selectivity;
            

            (gdb) p sel
            $29 = 100
            

            Then we hit the assert, as selectivity value is again absurd.

            So the discount should have only happened once not twice, we should make sure that selectivity for a field is discounted only once

            varun Varun Gupta (Inactive) added a comment - - edited ANALYSIS Looking at the test case in the description: The WHERE clause is A.a = B.a AND A.id=65 There is a primary key on A.id, so we will only read one table, hence so A is a const table. Then we substitute the value of A.a read from the const table in the condition A.a = B.a, so the condition now becomes B.a = 65. So the join planner picked ref access for table B The key is on column B.a (gdb) p table->alias.Ptr $11 = 0x7fffe00127e0 "B" (gdb) p table->cond_selectivity $9 = 0.01 (gdb) p pos->key $14 = (KEYUSE *) 0x7fffe000aa30 (gdb) p pos->key->key $15 = 1 (gdb) p table->quick_keys.is_set(key) $12 = true (gdb) p table->quick_rows[key] $13 = 1 Discount the seletivity for ref(const). sel /= ( double )table->quick_rows[key] / ( double ) table->stat_records(); After discount, we have (gdb) p sel $16 = 1 Discount selectivity for ref(non-const) Here we again consider the case B.a = A.a (gdb) p next_field->table->alias.Ptr $26 = 0x7fffe00126c0 "A" (gdb) p next_field->field_name $27 = 0x7fffe001055c "a" (gdb) p field->field_name $30 = 0x7fffe001055c "a" (gdb) p field->table->alias.Ptr $31 = 0x7fffe00127e0 "B" (gdb) p sel $28 = 1 (gdb) p field->cond_selectivity $33 = 0.01 So here the discount happens sel/= field->cond_selectivity; (gdb) p sel $29 = 100 Then we hit the assert, as selectivity value is again absurd. So the discount should have only happened once not twice, we should make sure that selectivity for a field is discounted only once
            varun Varun Gupta (Inactive) added a comment - Patch http://lists.askmonty.org/pipermail/commits/2019-September/014003.html
            varun Varun Gupta (Inactive) added a comment - - edited

            --source include/have_sequence.inc
            create table t1 (id int, a int, b int, key idx1(id), key idx2(a));
            insert into t1 select seq,seq, seq from seq_1_to_100;

            MariaDB [test]> set optimizer_use_condition_selectivity=1;
            Query OK, 0 rows affected (0.00 sec)
             
            MariaDB [test]> EXPLAIN SELECT * FROM t1 A, t1 B  WHERE A.id = B.a and A.id = 65;
            +------+-------------+-------+------+---------------+------+---------+-------+------+-------+
            | id   | select_type | table | type | possible_keys | key  | key_len | ref   | rows | Extra |
            +------+-------------+-------+------+---------------+------+---------+-------+------+-------+
            |    1 | SIMPLE      | A     | ref  | id            | id   | 5       | const |    1 |       |
            |    1 | SIMPLE      | B     | ref  | idx2          | idx2 | 5       | const |    1 |       |
            +------+-------------+-------+------+---------------+------+---------+-------+------+-------+
            2 rows in set (0.00 sec)
            

            Now lets consider the same query with
            optimizer_use_condition_selectivity=2

            EXPLAIN SELECT * FROM t1 A, t1 B WHERE A.id = B.a and A.id = 65;

            Table A has a sargable condition A.id = 65 [index idx1]
            Table B has a sargable condition B.a = 65 ( because A.id = 65) [index idx2]

            So for cond_selectivity for table B we would have selectivity(B.a=65) = table->quick_rows[1] / table_records

            Now while discounting in table_cond_selectivity for table B

            Case 1

            Check if we have a prefix of key=const that matches a quick select.
            Here we make the first discount for B.a = 65 , which makes sense

            Case 2

            Go through the remaining keypart where key_part_i=const equalities and find those that were
            already taken into account in table->cond_selectivity.This is not required for our example as the quick select matches all the keyparts in the WHERE clause for table B

            Case 3

            If the field f from the table is equal to a field from one the
            earlier joined tables then the selectivity of the range conditions
            over the field f must be discounted.

            In this case we discount the selectivity for the condition B.a = A.id. This is incorrect as we have already
            discounted the selecitvity for B.a=65 which is the same as B.a= A.id.

            varun Varun Gupta (Inactive) added a comment - - edited --source include/have_sequence.inc create table t1 (id int, a int, b int, key idx1(id), key idx2(a)); insert into t1 select seq,seq, seq from seq_1_to_100; MariaDB [test]> set optimizer_use_condition_selectivity=1; Query OK, 0 rows affected (0.00 sec)   MariaDB [test]> EXPLAIN SELECT * FROM t1 A, t1 B WHERE A.id = B.a and A.id = 65; +------+-------------+-------+------+---------------+------+---------+-------+------+-------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +------+-------------+-------+------+---------------+------+---------+-------+------+-------+ | 1 | SIMPLE | A | ref | id | id | 5 | const | 1 | | | 1 | SIMPLE | B | ref | idx2 | idx2 | 5 | const | 1 | | +------+-------------+-------+------+---------------+------+---------+-------+------+-------+ 2 rows in set (0.00 sec) Now lets consider the same query with optimizer_use_condition_selectivity=2 EXPLAIN SELECT * FROM t1 A, t1 B WHERE A.id = B.a and A.id = 65; Table A has a sargable condition A.id = 65 [index idx1] Table B has a sargable condition B.a = 65 ( because A.id = 65) [index idx2] So for cond_selectivity for table B we would have selectivity(B.a=65) = table->quick_rows [1] / table_records Now while discounting in table_cond_selectivity for table B Case 1 Check if we have a prefix of key=const that matches a quick select. Here we make the first discount for B.a = 65 , which makes sense Case 2 Go through the remaining keypart where key_part_i=const equalities and find those that were already taken into account in table->cond_selectivity.This is not required for our example as the quick select matches all the keyparts in the WHERE clause for table B Case 3 If the field f from the table is equal to a field from one the earlier joined tables then the selectivity of the range conditions over the field f must be discounted. In this case we discount the selectivity for the condition B.a = A.id. This is incorrect as we have already discounted the selecitvity for B.a=65 which is the same as B.a= A.id.

            The patch is ok to push.

            psergei Sergei Petrunia added a comment - The patch is ok to push.

            A larger change that addresses these problems is being worked on in MDEV-20740.

            marko Marko Mäkelä added a comment - A larger change that addresses these problems is being worked on in MDEV-20740 .

            I checked this test case against 10.7-selectivity and it works (no crash)
            I have added this test case to the 10.7-selectivty tree

            monty Michael Widenius added a comment - I checked this test case against 10.7-selectivity and it works (no crash) I have added this test case to the 10.7-selectivty tree

            psergei Can you please get the fix pushed to 10.11 and ensure that it is not getting into 11.4 (as this was already fixed in the 11.0 branch)

            monty Michael Widenius added a comment - psergei Can you please get the fix pushed to 10.11 and ensure that it is not getting into 11.4 (as this was already fixed in the 11.0 branch)

            People

              psergei Sergei Petrunia
              varun Varun Gupta (Inactive)
              Votes:
              1 Vote for this issue
              Watchers:
              9 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.