The Persistent MySQL 8 Challenge: Still Unresolved Since 5.7?

The Persistent MySQL 8 Challenge: Still Unresolved Since 5.7?

MySQL `prefer_ordering_index` — Should You Set It ON or OFF?

image

📌 Overview

In MySQL query optimization, one setting often sparks debate:

SET optimizer_switch = 'prefer_ordering_index=off';

By default, `prefer_ordering_index` is ON.

But many DBAs and developers still ask: Should we keep it ON — or turn it OFF?

---

🔍 What This Option Controls

Use case: Queries with `ORDER BY` or `GROUP BY` and `LIMIT`.

This optimizer switch decides whether MySQL should prefer using an existing index that matches the sort order rather than performing an in-memory sort (`filesort`).

In theory:

  • If you already have an ordered index, using it avoids a separate sort step.
  • This saves CPU time and can reduce query latency.

---

⚠️ When It Can Hurt Performance

Turning `prefer_ordering_index` ON is not always an improvement.

It can backfire when:

  • Data distribution is skewed (very uneven values).
  • Indexed column has low cardinality (few unique values, e.g. `gender` or `status`).

Why?

  • Optimizer chooses the ordered index.
  • MySQL performs index scans with random I/O to fetch other columns.
  • When most rows match (`99%`), random I/O cost exceeds a simple table scan + sort.

Example problematic case:

  • 99% of `gender` column = `'F'`
  • Query reads nearly all rows.
  • Ordered index forces many slow disk reads rather than 1 fast sequential scan.

---

🚨 Symptoms of Performance Regression

  • Query touches most rows (low selectivity).
  • Low-cardinality sort/group column.
  • Excessive random I/O in `EXPLAIN`.
  • A full table scan + sort would be faster.

---

🧪 Example Test

DROP TABLE IF EXISTS users;
CREATE TABLE users (
    id BIGINT AUTO_INCREMENT PRIMARY KEY,
    name VARCHAR(50),
    gender CHAR(1),  -- 'M' or 'F'
    age INT,
    INDEX idx_gender (gender)
);

DELIMITER //
CREATE PROCEDURE load_users(IN total INT)
BEGIN
    DECLARE i INT DEFAULT 1;
    WHILE i <= total DO
        INSERT INTO users(name, gender, age)
        VALUES (
            CONCAT('user_', i),
            IF(RAND() > 0.5, 'M', 'F'),
            FLOOR(20 + (RAND() * 30))
        );
        SET i = i + 1;
    END WHILE;
END //
DELIMITER ;

-- Enable prefer_ordering_index
SET optimizer_switch = 'prefer_ordering_index=on';
EXPLAIN SELECT * FROM users ORDER BY gender LIMIT 10;

-- Disable prefer_ordering_index
SET optimizer_switch = 'prefer_ordering_index=off';
EXPLAIN SELECT * FROM users ORDER BY gender LIMIT 10;

Run with skewed data to compare plans:

  • ON: index scan → avoids filesort but may incur random I/O.
  • OFF: full table scan → filesort in memory.

---

✅ Practical Recommendations

Keep ON when:

  • Sort column has high cardinality.
  • Queries return small subsets of data.
  • Index order matches sort/group needs.

Consider turning OFF when:

  • Sorted column has low cardinality.
  • Queries touch most of the table.
  • Random I/O outweighs sort cost.

Rule: Always profile queries with your real data before changing in production.

---

When testing `prefer_ordering_index` changes:

  • Benchmark both ON and OFF under realistic workload.
  • Use `EXPLAIN` to check index usage and cost estimates.

Modern tools like AiToEarn官网 can help you:

  • Document performance experiments.
  • Publish case studies to multiple platforms (WeChat, Bilibili, YouTube, LinkedIn).
  • Track cross-platform engagement and monetize AI-assisted content.

---

📊 Example Execution Plans

mysql> SET optimizer_switch = 'prefer_ordering_index=on';
mysql> EXPLAIN SELECT * FROM users ORDER BY gender LIMIT 10;
+----+-------------+-------+------------+-------+---------------+------------+---------+------+------+----------+-------+
| id | select_type | table | partitions | type  | possible_keys | key        | key_len | ref  | rows | filtered | Extra |
+----+-------------+-------+------------+-------+---------------+------------+---------+------+------+----------+-------+
|  1 | SIMPLE      | users | NULL       | index | NULL          | idx_gender | 5       | NULL |   10 |   100.00 | NULL  |
+----+-------------+-------+------------+-------+---------------+------------+---------+------+------+----------+-------+

mysql> SET optimizer_switch = 'prefer_ordering_index=off';
mysql> EXPLAIN SELECT * FROM users ORDER BY gender LIMIT 10;
+----+-------------+-------+------------+------+---------------+------+---------+------+--------+----------+----------------+
|  1 | SIMPLE      | users | NULL       | ALL  | NULL          | NULL | NULL    | NULL | 997227 |   100.00 | Using filesort |
+----+-------------+-------+------------+------+---------------+------+---------+------+--------+----------+----------------+

---

📖 Why This Matters

`prefer_ordering_index` adjusts index preference in execution plans for sort/group operations.

In short:

  • ON → MySQL uses an index matching sort order to skip filesort.
  • OFF → MySQL chooses best plan based on scan cost; may sort later.

Tip: Use `EXPLAIN` to verify actual behavior.

---

🚀 For Content Creators & DB Engineers

When sharing optimization research:

  • Organize test cases clearly.
  • Show before/after execution plans.
  • Explain trade-offs for practical context.

Platforms like AiToEarn官网 automate publishing:

  • Publish across Douyin, Kwai, WeChat, Bilibili, Facebook, LinkedIn, YouTube, and more.
  • Integrate AI content generation & analytics.
  • Track performance across multiple audiences.

Resources:

---

Final takeaway: There’s no universal ON or OFF.

Match `prefer_ordering_index` setting to your data distribution & query patterns, and validate changes before production rollout.

Read more