Description:
For InnoDB tables, DDL operations are primarily managed within the InnoDB engine. The most critical steps involve scanning the old table (by primary key) and building new B+trees (for indexes).
Taking OPTIMIZE TABLE as an example, since version 8.0.27, the scanning phase is handled by the Parallel_reader, while the building phases are taken care of by the Builder.
I noticed that in the Builder::bulk_add_row method, rows are initially added to a key buffer (using add_to_key_buffer). Once the key buffer becomes full, the data is either written to a temporary file (in the case of secondary keys) or inserted directly into the B+ tree (for the primary key).
Currently, the code calls key_buffer_sort whenever the key buffer is full. However, if the Builder is working on the primary key, sorting the key buffer is unnecessary because the primary key is inherently sorted.
How to repeat:
No need.
Suggested fix:
--- a/storage/innobase/ddl/ddl0builder.cc
+++ b/storage/innobase/ddl/ddl0builder.cc
@@ -1468,12 +1468,6 @@ dberr_t Builder::bulk_add_row(Cursor &cursor, Row &row, size_t thread_id,
if (!key_buffer->empty()) {
ut_a(err == DB_SUCCESS || err == DB_OVERFLOW);
- err = key_buffer_sort(thread_id);
-
- if (err != DB_SUCCESS) {
- set_error(err);
- return get_error();
- }
if (is_skip_file_sort()) {
if (!cursor.eof()) {
@@ -1512,6 +1506,13 @@ dberr_t Builder::bulk_add_row(Cursor &cursor, Row &row, size_t thread_id,
ut_a(m_btr_load == nullptr);
return DB_END_OF_INDEX;
+ } else {
+ err = key_buffer_sort(thread_id);
+
+ if (err != DB_SUCCESS) {
+ set_error(err);
+ return get_error();
+ }
}
}