MDEV-34043 Drastically slower query performance between CentOS (2sec) and Rocky (48sec)

One cause of the slowdown is because the ftruncate call can be much
slower on some systems.  ftruncate() is called by Aria for internal
temporary tables, tables created by the optimizer, when the upper level
asks Aria to delete the previous result set. This is needed when some
content from previous tables changes.

I have now changed Aria so that for internal temporary tables we don't
call ftruncate() anymore for maria_delete_all_rows().

I also had to update the Aria repair code to use the logical datafile
size and not the on-disk datafile size, which may contain data from a
previous result set.  The repair code is called to create indexes for
the internal temporary table after it is filled.
I also replaced a call to mysql_file_size() with a pwrite() in
_ma_bitmap_create_first().

Reviewer: Sergei Petrunia <sergey@mariadb.com>
Tester: Dave Gosselin <dave.gosselin@mariadb.com>
This commit is contained in:
Monty 2024-08-20 11:31:58 +03:00
parent eadf0f63a2
commit 1f040ae048
3 changed files with 44 additions and 14 deletions

View file

@ -3070,21 +3070,25 @@ my_bool _ma_check_if_right_bitmap_type(MARIA_HA *info,
int _ma_bitmap_create_first(MARIA_SHARE *share)
{
uint block_size= share->bitmap.block_size;
size_t error;
File file= share->bitmap.file.file;
uchar marker[CRC_SIZE];
uchar *temp_buff;
if (!(temp_buff= (uchar*) my_alloca(block_size)))
return 1;
bzero(temp_buff, block_size);
/*
Next write operation of the page will write correct CRC
if it is needed
*/
int4store(marker, MARIA_NO_CRC_BITMAP_PAGE);
int4store(temp_buff + block_size - CRC_SIZE, MARIA_NO_CRC_BITMAP_PAGE);
if (mysql_file_chsize(file, block_size - sizeof(marker),
0, MYF(MY_WME)) ||
my_pwrite(file, marker, sizeof(marker),
block_size - sizeof(marker),
MYF(MY_NABP | MY_WME)))
error= my_pwrite(file, temp_buff, block_size, 0, MYF(MY_NABP | MY_WME));
my_afree(temp_buff);
if (error)
return 1;
share->state.state.data_file_length= block_size;
_ma_bitmap_delete_all(share);
return 0;

View file

@ -418,6 +418,8 @@ int maria_chk_size(HA_CHECK *param, register MARIA_HA *info)
/* We cannot check file sizes for S3 */
DBUG_RETURN(0);
}
/* We should never come here with internal temporary tables */
DBUG_ASSERT(!share->internal_table);
if (!(param->testflag & T_SILENT))
puts("- check file-size");
@ -713,6 +715,8 @@ static int chk_index_down(HA_CHECK *param, MARIA_HA *info,
MARIA_PAGE ma_page;
DBUG_ENTER("chk_index_down");
DBUG_ASSERT(!share->internal_table);
/* Key blocks must lay within the key file length entirely. */
if (page + keyinfo->block_length > share->state.state.key_file_length)
{
@ -2464,7 +2468,16 @@ static int initialize_variables_for_repair(HA_CHECK *param,
return 1;
/* calculate max_records */
sort_info->filelength= my_seek(info->dfile.file, 0L, MY_SEEK_END, MYF(0));
if (!share->internal_table)
{
/* Get real file size */
sort_info->filelength= my_seek(info->dfile.file, 0L, MY_SEEK_END, MYF(0));
}
else
{
/* For internal temporary files we are using the logical file length */
sort_info->filelength= share->state.state.data_file_length;
}
param->max_progress= sort_info->filelength;
if ((param->testflag & T_CREATE_MISSING_KEYS) ||
@ -2860,7 +2873,8 @@ int maria_repair(HA_CHECK *param, register MARIA_HA *info,
{
fputs(" \r",stdout); fflush(stdout);
}
if (mysql_file_chsize(share->kfile.file,
if (!share->internal_table &&
mysql_file_chsize(share->kfile.file,
share->state.state.key_file_length, 0, MYF(0)))
{
_ma_check_print_warning(param,
@ -4168,7 +4182,8 @@ int maria_repair_by_sort(HA_CHECK *param, register MARIA_HA *info,
if (param->testflag & T_CALC_CHECKSUM)
share->state.state.checksum=param->glob_crc;
if (mysql_file_chsize(share->kfile.file,
if (!share->internal_table &&
mysql_file_chsize(share->kfile.file,
share->state.state.key_file_length, 0, MYF(0)))
_ma_check_print_warning(param,
"Can't change size of indexfile, error: %d",
@ -4706,7 +4721,8 @@ int maria_repair_parallel(HA_CHECK *param, register MARIA_HA *info,
if (param->testflag & T_CALC_CHECKSUM)
share->state.state.checksum=param->glob_crc;
if (mysql_file_chsize(share->kfile.file,
if (!share->internal_table &&
mysql_file_chsize(share->kfile.file,
share->state.state.key_file_length, 0, MYF(0)))
_ma_check_print_warning(param,
"Can't change size of indexfile, error: %d",
@ -6108,6 +6124,8 @@ int maria_test_if_almost_full(MARIA_HA *info)
{
MARIA_SHARE *share= info->s;
DBUG_ASSERT(!share->internal_table);
if (share->options & HA_OPTION_COMPRESS_RECORD)
return 0;
return mysql_file_seek(share->kfile.file, 0L, MY_SEEK_END,

View file

@ -103,9 +103,17 @@ int maria_delete_all_rows(MARIA_HA *info)
#endif
if (_ma_flush_table_files(info, MARIA_FLUSH_DATA|MARIA_FLUSH_INDEX,
FLUSH_IGNORE_CHANGED, FLUSH_IGNORE_CHANGED) ||
mysql_file_chsize(info->dfile.file, 0, 0, MYF(MY_WME)) ||
mysql_file_chsize(share->kfile.file, share->base.keystart, 0, MYF(MY_WME)))
FLUSH_IGNORE_CHANGED, FLUSH_IGNORE_CHANGED))
goto err;
/*
Avoid truncate of internal temporary tables as this can have a big
performance overhead when called by mysql_handle_single_derived()
tables in MariaDB as part of split materialization.
*/
if (!share->internal_table &&
(mysql_file_chsize(info->dfile.file, 0, 0, MYF(MY_WME)) ||
mysql_file_chsize(share->kfile.file, share->base.keystart, 0,
MYF(MY_WME))))
goto err;
if (_ma_initialize_data_file(share, info->dfile.file))