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

Prefix index on VARCHAR PRIMARY KEY column causes equality lookup to return 0 rows (wrong result) when optimizer chooses const access via the prefix index

    XMLWordPrintable

Details

    Description

      When a table has a VARCHAR column defined as PRIMARY KEY and a prefix
      index on that same column with a short prefix length (e.g., 1
      character), an equality lookup on the column may return 0 rows
      instead of the correct 1 row. The bug is deterministic and reproduces
      every time.

      The key condition is that the optimizer chooses to use the prefix
      index for the lookup, producing an EXPLAIN plan with type=const and
      key=prefix_c0_117. Despite the EXPLAIN showing rows=2 with
      Extra=Using where (indicating 2 candidate rows from the index that
      need filtering), the WHERE filter incorrectly eliminates all rows and
      returns an empty result set.

      The same query using the PRIMARY KEY index (via IGNORE INDEX or
      natural optimizer choice) correctly returns 1 row.

      How to repeat

      Run the following minimal SQL script:

      DROP DATABASE IF EXISTS test_db5_minimal;
      CREATE DATABASE test_db5_minimal;
      USE test_db5_minimal;

      CREATE TABLE t1(c0 VARCHAR(100), PRIMARY KEY(c0));
      INSERT INTO t1 VALUES ('');
      INSERT INTO t1 VALUES ('-1221357719');
      INSERT INTO t1 VALUES ('o}_42''qT');
      INSERT INTO t1 VALUES ('-1632889459');
      INSERT INTO t1 VALUES ('JON');

      – Create prefix index with length 1 on c0
      CREATE INDEX prefix_c0_117 ON t1 (c0(1));

      – BUG: This returns 0 rows (WRONG)
      SELECT '=== FORCE INDEX (returns 0 rows - BUG) ===' AS test;
      SELECT c0 FROM t1 FORCE INDEX(prefix_c0_117) WHERE c0 = '-1632889459' ORDER BY c0 LIMIT 100;

      – Correct: This returns 1 row (CORRECT)
      SELECT '=== IGNORE INDEX (returns 1 row - CORRECT) ===' AS test;
      SELECT c0 FROM t1 IGNORE INDEX(prefix_c0_117) WHERE c0 = '-1632889459' ORDER BY c0 LIMIT 100;

      – EXPLAIN plans for reference:
      – FORCE INDEX: type=const, key=prefix_c0_117, key_len=6, rows=2, Extra=Using where
      – IGNORE INDEX: type=const, key=PRIMARY, key_len=402, rows=1

      Expected result: Both queries return 1 row with c0='-1632889459'.
      Actual result: The FORCE INDEX query returns 0 rows.

      Attachments

        Activity

          People

            psergei Sergei Petrunia
            ZyanNo1 Zeyan Li
            Votes:
            0 Vote for this issue
            Watchers:
            2 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.