/* Reserve free space from every block for key_version */ #define ROW_MERGE_RESERVE_SIZE 4
/* Cluster index read task is mandatory */ #define COST_READ_CLUSTERED_INDEX 1.0
/* Basic fixed cost to build all type of index */ #define COST_BUILD_INDEX_STATIC 0.5 /* Dynamic cost to build all type of index, dynamic cost will be re-distributed based on page count ratio of each index */ #define COST_BUILD_INDEX_DYNAMIC 0.5
/* Sum of below two must be 1.0 */ #define PCT_COST_MERGESORT_INDEX 0.4 #define PCT_COST_INSERT_INDEX 0.6
// Forward declaration struct ib_sequence_t;
/** @brief Block size for I/O operations in merge sort.
TheformatisthesameasarecordinROW_FORMAT=COMPACTwiththe
exception that the REC_N_NEW_EXTRA_BYTES are omitted. */ typedef byte mrec_t;
/** Merge record in row_merge_buf_t */ struct mtuple_t {
dfield_t* fields; /*!< data fields */
};
/** Buffer for sorting in main memory. */ struct row_merge_buf_t {
mem_heap_t* heap; /*!< memory heap where allocated */
dict_index_t* index; /*!< the index the tuples belong to */
ulint total_size; /*!< total amount of data bytes */
ulint n_tuples; /*!< number of data tuples */
ulint max_tuples; /*!< maximum number of data tuples */
mtuple_t* tuples; /*!< array of data tuples */
mtuple_t* tmp_tuples; /*!< temporary copy of tuples,
for sorting */
};
/** Information about temporary files used in merge sort */ struct merge_file_t {
pfs_os_file_t fd; /*!< file descriptor */
ulint offset; /*!< file offset (end of file) */
ib_uint64_t n_rec; /*!< number of records in the file */
};
/** Index field definition */ struct index_field_t {
ulint col_no; /*!< column offset */
ulint prefix_len; /*!< column prefix length, or 0
if indexing the whole column */ bool is_v_col; /*!< whether this is a virtual column */ bool descending; /*!< whether to use DESC order */
};
/** Definition of an index being created */ struct index_def_t { constchar* name; /*!< index name */ bool rebuild; /*!< whether the table is rebuilt */
ulint ind_type; /*!< 0, DICT_UNIQUE,
or DICT_CLUSTERED */
ulint key_number; /*!< MySQL key number,
or ULINT_UNDEFINED if none */
ulint n_fields; /*!< number of fields in index */
index_field_t* fields; /*!< field definitions */
st_mysql_ftparser*
parser; /*!< fulltext parser plugin */
};
/** Structure for reporting duplicate records. */ struct row_merge_dup_t {
dict_index_t* index; /*!< index being sorted */
trx_t* trx; /*!< transaction */ struct TABLE* table; /*!< MySQL table object */ const ulint* col_map;/*!< mapping of column numbers intabletotherebuilttable (index->table),orNULLifnot
rebuilding table */
ulint n_dup; /*!< number of duplicates */
};
/*************************************************************//**
Report a duplicate key. */ void
row_merge_dup_report( /*=================*/
row_merge_dup_t* dup, /*!< in/out: for reporting duplicates */ const dfield_t* entry) /*!< in: duplicate index entry */
MY_ATTRIBUTE((nonnull));
/** Drop indexes that were created before an error occurred. Thedatadictionarymusthavebeenlockedexclusivelybythecaller, becausethetransactionwillnotbecommitted. @paramtrxdictionarytransaction @paramtabletablecontainingtheindexes @paramlockedTrueiftableislocked, false-mayneedtodolazydrop
@param alter_trx Alter table transaction */ void
row_merge_drop_indexes(
trx_t* trx,
dict_table_t* table, bool locked, const trx_t* alter_trx=NULL);
/** During recovery, drop recovered index stubs that were created in
prepare_inplace_alter_table_dict(). */ void row_merge_drop_temp_indexes();
/** Create a temporary file at the specified path. @parampathlocationforcreatingtemporarymergefiles,ornullptr
@return File descriptor */
pfs_os_file_t row_merge_file_create_low(constchar *path)
MY_ATTRIBUTE((warn_unused_result)); /*********************************************************************//**
Destroy a merge file. And de-register the file from Performance Schema if UNIV_PFS_IO is defined. */ void
row_merge_file_destroy_low( /*=======================*/ const pfs_os_file_t& fd); /*!< in: merge file descriptor */
/*********************************************************************//**
Rename an index in the dictionary that was created. The data
dictionary must have been locked exclusively by the caller, because
the transaction will not be committed.
@return DB_SUCCESS if all OK */
dberr_t
row_merge_rename_index_to_add( /*==========================*/
trx_t* trx, /*!< in/out: transaction */
table_id_t table_id, /*!< in: table identifier */
index_id_t index_id) /*!< in: index identifier */
MY_ATTRIBUTE((nonnull(1), warn_unused_result));
/** Create the index and load in to the dictionary. @param[in,out]tabletheindexisonthistable @param[in]index_deftheindexdefinition @param[in]add_vnewvirtualcolumnsaddedalongwithadd indexcall
@return index, or NULL on error */
dict_index_t*
row_merge_create_index(
dict_table_t* table, const index_def_t* index_def, const dict_add_v_col_t* add_v)
MY_ATTRIBUTE((warn_unused_result));
/*********************************************************************//**
Check if a transaction can use an index.
@return whether the index can be used by the transaction */ bool
row_merge_is_index_usable( /*======================*/ const trx_t* trx, /*!< in: transaction */ const dict_index_t* index) /*!< in: index to check */
MY_ATTRIBUTE((nonnull, warn_unused_result));
/** Map from column numbers to column definitions that include changestothecollation,whentheencodingiscompatiblewith
the original column and no table rebuild is needed */ typedef std::map<unsigned, dict_col_t*> col_collations;
/** Write a buffer to a block. @parambufsortedbuffer @paramblockbufferforwritingtofile
@param blob_file blob file handle for doing bulk insert operation */
dberr_t row_merge_buf_write(const row_merge_buf_t *buf, #ifndef DBUG_OFF const merge_file_t *of, /*!< output file */ #endif
row_merge_block_t *block,
merge_file_t *blob_file= nullptr);
/********************************************************************//**
Sort a buffer. */ void
row_merge_buf_sort( /*===============*/
row_merge_buf_t* buf, /*!< in/out: sort buffer */
row_merge_dup_t* dup) /*!< in/out: reporter of duplicates
(NULL if non-unique index) */
MY_ATTRIBUTE((nonnull(1)));
/********************************************************************//**
Write a merge block to the file system.
@return whether the request was completed successfully
@retval false on error
@retval true on success */ bool
row_merge_write( const pfs_os_file_t& fd, /*!< in: file descriptor */
ulint offset, /*!< in: offset where to write,
in number of row_merge_block_t elements */ constvoid* buf, /*!< in: data */ void* crypt_buf, /*!< in: crypt buf or NULL */
ulint space) /*!< in: space id */
MY_ATTRIBUTE((warn_unused_result));
/** Create a merge file in the given location. @param[out]merge_filemergefilestructure @param[in]pathlocationforcreatingtemporaryfile,orNULL
@return file descriptor, or -1 on failure */
pfs_os_file_t
row_merge_file_create(
merge_file_t* merge_file, constchar* path)
MY_ATTRIBUTE((warn_unused_result, nonnull(1)));
/** Read a merge block from the file system.
@return whether the request was completed successfully */ bool
row_merge_read( /*===========*/ const pfs_os_file_t& fd, /*!< in: file descriptor */
ulint offset, /*!< in: offset where to read innumberofrow_merge_block_t
elements */
row_merge_block_t* buf, /*!< out: data */
row_merge_block_t* crypt_buf, /*!< in: crypt buf or NULL */
ulint space) /*!< in: space id */
MY_ATTRIBUTE((warn_unused_result));
/********************************************************************//**
Read a merge record.
@return pointer to next record, or NULL on I/O error or end of list */ const byte*
row_merge_read_rec( /*===============*/
row_merge_block_t* block, /*!< in/out: file buffer */
mrec_buf_t* buf, /*!< in/out: secondary buffer */ const byte* b, /*!< in: pointer to record */ const dict_index_t* index, /*!< in: index of the record */ const pfs_os_file_t& fd, /*!< in: file descriptor */
ulint* foffs, /*!< in/out: file offset */ const mrec_t** mrec, /*!< out: pointer to merge record, orNULLonendoflist
(non-NULL on I/O error) */
rec_offs* offsets,/*!< out: offsets of mrec */
row_merge_block_t* crypt_block, /*!< in: crypt buf or NULL */
ulint space) /*!< in: space id */
MY_ATTRIBUTE((warn_unused_result));
/* Report an InnoDB error to the client by invoking my_error(). @paramerrorInnoDBerrorcode @paramtabletablename
@param flags table flags */
ATTRIBUTE_COLD __attribute__((nonnull)) void
my_error_innodb(dberr_t error, constchar *table, ulint flags);
/** Buffer for bulk insert */ class row_merge_bulk_t
{ /** Buffer for each index in the table. main memory
buffer for sorting the index */
row_merge_buf_t *m_merge_buf; /** Block for IO operation */
row_merge_block_t *m_block= nullptr; /** File to store the buffer and used for merge sort */
merge_file_t *m_merge_files= nullptr; /** Temporary file to be used for merge sort */
pfs_os_file_t m_tmpfd; /** Allocate memory for merge file data structure */
ut_allocator<row_merge_block_t> m_alloc; /** Storage for description for the m_alloc */
ut_new_pfx_t m_block_pfx; /** Temporary file to store the blob */
merge_file_t m_blob_file; /** Storage for description for the crypt_block */
ut_new_pfx_t m_crypt_pfx; /** Block for encryption */
row_merge_block_t *m_crypt_block= nullptr; public: /** If this is false, then there will be only one bulk_insert_buffered()callfortheprimarykeyfollowedby load_one_row()androw_ins_clust_index_entry()forsubsequentrows. Forsecondaryindexesorfortrue,bulk_insert_buffered()willbe
invoked for each row. */ constbool m_sort_primary_key; /** Constructor. Createallmergefiles,mergebufferforallthetableindexes expectftsindexes. CreateamergeblockwhichisusedtowriteIOoperation @paramtabletablewhichundergoesbulkinsertoperation @paramsort_primary_keyAllowprimarykeysortforbulk operation.Incaseofload,InnoDBskipsthe
primary key sorting */
row_merge_bulk_t(dict_table_t *table, bool sort_primary_key);
/** Destructor.
Remove all merge files, merge buffer for all table indexes. */
~row_merge_bulk_t();
/** Remove all buffer for the table indexes */ void remove_all_bulk_buffer();
/** Clean the merge buffer for the given index number */ void clean_bulk_buffer(ulint index_no);
/** Create the temporary file for the given index number
@retval true if temporary file creation went well */ bool create_tmp_file(ulint index_no);
/** Write the merge buffer to the tmp file for the given indexnumber.
@param index_no buffer to be written for the index */
dberr_t write_to_tmp_file(ulint index_no);
/** Add the tuple to the merge buffer for the given index. Ifthebufferranoutofmemorythenwritethebufferinto thetemporaryfileanddoinsertthetupleagain. @paramrowtupletobeinserted @paramindindextobebuffered
@param trx bulk transaction */
dberr_t bulk_insert_buffered(const dtuple_t &row, const dict_index_t &ind,
trx_t *trx);
/** Do bulk insert operation into the index tree from bufferormergefileifexists @paramindex_noindextobeinserted
@param trx bulk transaction */
dberr_t write_to_index(ulint index_no, trx_t *trx);
/** Do bulk insert for the buffered insert for the table. @paramtabletablewhichundergoesforbulkinsertoperation
@param trx bulk transaction */
dberr_t write_to_table(dict_table_t *table, trx_t *trx);
/** Allocate block for writing the buffer into disk */
dberr_t alloc_block();
/** Init temporary files for each index */ void init_tmp_file();
/** Load one row into the primary index @paramtrxbulktransaction
@return error code */
dberr_t load_one_row(trx_t *trx);
};
Messung V0.5 in Prozent
¤ Dauer der Verarbeitung: 0.23 Sekunden
(vorverarbeitet am 2026-10-08)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.