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

Stats are not dropped for ALTER TABLE ... MODIFY ..., ALGORITHM=COPY

    XMLWordPrintable

Details

    Description

      Split from MDEV-31182, based on https://jira.mariadb.org/browse/MDEV-31182?focusedCommentId=334675&page=com.atlassian.jira.plugin.system.issuetabpanels%3Acomment-tabpanel#comment-334675

      Consider

      SET histogram_type = DOUBLE_PREC_HB;
       
      CREATE TABLE t (a INT);
      INSERT INTO t VALUES (1),(2);
      ANALYZE TABLE t PERSISTENT FOR ALL;
      select db_name, table_name, min_value, max_value, hex(histogram) from mysql.column_stats where table_name='t';
      ALTER TABLE t MODIFY a BLOB, ALGORITHM=COPY;
      select db_name, table_name, min_value, max_value, hex(histogram) from mysql.column_stats where table_name='t';
       
      SELECT a FROM t WHERE a LIKE '1%';
       
      DROP TABLE t;
      

      Here the ATLER TABLE statement does not drop the column stats. If we remove ALGORITHM=COPY then it does drop them. This is because the marking for dropping is only done in fill_alter_inplace_info.

      // in mysql_alter_table:
        if (alter_info->algorithm(thd) != Alter_info::ALTER_TABLE_ALGORITHM_COPY)
        {
      //  [... 8 lines elided]
          /* Fill the Alter_inplace_info structure. */
          if (fill_alter_inplace_info(thd, table, &ha_alter_info))
      // in fill_alter_inplace_info:
            /*
              Check if type of column has changed.
            */
            bool is_equal= field->is_equal(*new_field);
      //  [... 24 lines elided]
            if (!is_equal)
            {
              if (field->table->file->can_convert_nocopy(*field, *new_field))
      //  [... 8 lines elided]
              else
              {
                /* New column type is incompatible with old one. */
                ha_alter_info->handler_flags|= field->stored_in_db()
                                                   ? ALTER_STORED_COLUMN_TYPE
                                                   : ALTER_VIRTUAL_COLUMN_TYPE;
       
                if (table->s->tmp_table == NO_TMP_TABLE)
                {
                  if (alter_info->drop_stat_fields.push_back(field, thd->mem_root))
                    DBUG_RETURN(true);
      

      The criteria for dropping also looks strange, it first checks for field type equality, and if they are unequal, checks can_convert_nocopy. If stats for a column need to be dropped, whether for inplace alter or not, they need to be dropped for any kind of field change that is incompatible for range comparison. can_convert_nocopy is a handler method so each handler can have its own implementation. The name suggests it determines convertibility for the purpose of non-COPY altering. It is not clear whether it implies convertibility for stats preservation. Likely not as the innodb implementation returns false for smaller int to larger int, not to mention that the default implementation always returns false. The criteria should be something like the supertype check implemented in MDEV-38752.

      Attachments

        Issue Links

          Activity

            People

              ycp Yuchen Pei
              ycp Yuchen Pei
              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.