32 #include "probes_mysql.h"
33 #include "opt_range.h"
34 #include "bounded_queue.h"
35 #include "filesort_utils.h"
39 #include "sql_optimizer.h"
48 static uchar *read_buffpek_from_file(
IO_CACHE *buffer_file, uint count,
58 static void register_used_fields(
Sort_param *param);
59 static int merge_index(
Sort_param *param,uchar *sort_buffer,
63 static bool save_index(
Sort_param *param, uint count,
65 static uint suffix_length(ulong string_length);
74 ha_rows records, ulong memory_available);
77 void Sort_param::init_for_filesort(uint sortlen,
TABLE *
table,
78 ulong max_length_for_sort_data,
79 ha_rows maxrows,
bool sort_positions)
84 !table->fulltext_searched && !sort_positions)
90 addon_field= get_addon_fields(max_length_for_sort_data,
91 table->field, sort_length, &addon_length);
94 res_length= addon_length;
97 res_length= ref_length;
102 sort_length+= ref_length;
104 rec_length= sort_length + addon_length;
110 const SORT_FIELD *sortorder,
113 if (!trace->is_started())
117 for (; s_length-- ; sortorder++)
120 oto.add_alnum(
"direction", sortorder->reverse ?
"desc" :
"asc");
122 if (sortorder->field)
124 if (strlen(sortorder->field->table->alias) != 0)
125 oto.add_utf8_table(sortorder->field->table);
127 oto.add_alnum(
"table",
"intermediate_tmp_table");
128 oto.add_alnum(
"field", sortorder->field->field_name ?
129 sortorder->field->field_name :
"tmp_table_column");
132 oto.add(
"expression", sortorder->item);
174 bool sort_positions, ha_rows *examined_rows,
178 ulong memory_available= thd->variables.sortbuff_size;
181 ha_rows num_rows= HA_POS_ERROR;
182 IO_CACHE tempfile, buffpek_pointers, *outfile;
184 bool multi_byte_charset;
188 ha_rows max_rows= filesort->
limit;
191 DBUG_ENTER(
"filesort");
193 if (!(s_length= filesort->make_sortorder()))
194 DBUG_RETURN(HA_POS_ERROR);
201 trace_filesort_information(trace, filesort->
sortorder, s_length);
203 #ifdef SKIP_DBUG_IN_FILESORT
207 table->reginfo.join_tab->join->
select_lex->master_unit()->item :
210 MYSQL_FILESORT_START(table->s->db.str, table->s->table_name.str);
211 DEBUG_SYNC(thd,
"filesort_start");
225 table->sort.io_cache= NULL;
226 DBUG_ASSERT(table_sort.record_pointers == NULL);
228 outfile= table_sort.io_cache;
229 my_b_clear(&tempfile);
230 my_b_clear(&buffpek_pointers);
235 &multi_byte_charset),
237 thd->variables.max_length_for_sort_data,
238 max_rows, sort_positions);
240 table_sort.addon_buf= 0;
241 table_sort.addon_length= param.addon_length;
242 table_sort.addon_field= param.addon_field;
243 table_sort.unpack= unpack_addon_fields;
244 if (param.addon_field &&
245 !(table_sort.addon_buf=
246 (uchar *) my_malloc(param.addon_length, MYF(MY_WME))))
249 if (select && select->quick)
250 thd->inc_status_sort_range();
252 thd->inc_status_sort_scan();
257 if (multi_byte_charset &&
258 !(param.tmp_buffer= (
char*) my_malloc(param.sort_length,MYF(MY_WME))))
261 if (check_if_pq_applicable(trace, ¶m, &table_sort,
262 table, num_rows, memory_available))
264 DBUG_PRINT(
"info", (
"filesort PQ is applicable"));
265 const size_t compare_length= param.sort_length;
266 if (pq.
init(param.max_rows,
276 DBUG_PRINT(
"info", (
"failed to allocate PQ"));
277 table_sort.free_sort_buffer();
278 DBUG_ASSERT(thd->is_error());
282 table_sort.init_record_pointers();
287 DBUG_PRINT(
"info", (
"filesort PQ is not applicable"));
289 const ulong min_sort_memory=
290 max(MIN_SORT_MEMORY, param.sort_length * MERGEBUFF2);
291 while (memory_available >= min_sort_memory)
293 ha_rows keys= memory_available / (param.rec_length +
sizeof(
char*));
294 param.max_keys_per_buffer= (uint) min(num_rows, keys);
295 if (table_sort.get_sort_keys())
298 if (std::make_pair(param.max_keys_per_buffer, param.rec_length) !=
299 table_sort.sort_buffer_properties())
305 table_sort.free_sort_buffer();
308 table_sort.alloc_sort_buffer(param.max_keys_per_buffer, param.rec_length);
309 if (table_sort.get_sort_keys())
311 ulong old_memory_available= memory_available;
312 memory_available= memory_available/4*3;
313 if (memory_available < min_sort_memory &&
314 old_memory_available > min_sort_memory)
315 memory_available= min_sort_memory;
317 if (memory_available < min_sort_memory)
319 my_error(ER_OUT_OF_SORTMEMORY,MYF(ME_ERROR + ME_FATALERROR));
324 if (open_cached_file(&buffpek_pointers,mysql_tmpdir,TEMP_PREFIX,
325 DISK_BUFFER_SIZE, MYF(MY_WME)))
328 param.sort_form=
table;
329 param.end= (param.local_sortorder= filesort->
sortorder) + s_length;
333 num_rows= find_all_keys(¶m, select,
339 if (num_rows == HA_POS_ERROR)
343 maxbuffer= (uint) (my_b_tell(&buffpek_pointers)/
sizeof(*buffpek));
346 .add(
"rows", num_rows)
347 .add(
"examined_rows", param.examined_rows)
348 .add(
"number_of_tmp_files", maxbuffer)
349 .add(
"sort_buffer_size", table_sort.sort_buffer_size())
350 .add_alnum(
"sort_mode",
352 "<sort_key, additional_fields>" :
"<sort_key, rowid>");
356 if (save_index(¶m, (uint) num_rows, &table_sort))
362 DBUG_ASSERT(param.sort_length != 0);
364 if (table_sort.buffpek && table_sort.buffpek_len < maxbuffer)
366 my_free(table_sort.buffpek);
367 table_sort.buffpek= 0;
369 if (!(table_sort.buffpek=
370 (uchar *) read_buffpek_from_file(&buffpek_pointers, maxbuffer,
371 table_sort.buffpek)))
373 buffpek= (
BUFFPEK *) table_sort.buffpek;
374 table_sort.buffpek_len= maxbuffer;
375 close_cached_file(&buffpek_pointers);
377 if (! my_b_inited(outfile) &&
378 open_cached_file(outfile,mysql_tmpdir,TEMP_PREFIX,READ_RECORD_BUFFER,
381 if (reinit_io_cache(outfile,WRITE_CACHE,0L,0,0))
388 param.max_keys_per_buffer= table_sort.sort_buffer_size() / param.rec_length;
391 (uchar*) table_sort.get_sort_keys(),
395 if (flush_io_cache(&tempfile) ||
396 reinit_io_cache(&tempfile,READ_CACHE,0L,0,0))
398 if (merge_index(¶m,
399 (uchar*) table_sort.get_sort_keys(),
407 if (num_rows > param.max_rows)
410 num_rows= param.max_rows;
415 my_free(param.tmp_buffer);
416 if (!subselect || !subselect->is_uncacheable())
418 table_sort.free_sort_buffer();
420 table_sort.buffpek= 0;
421 table_sort.buffpek_len= 0;
423 close_cached_file(&tempfile);
424 close_cached_file(&buffpek_pointers);
425 if (my_b_inited(outfile))
427 if (flush_io_cache(outfile))
430 my_off_t save_pos=outfile->pos_in_file;
432 if (reinit_io_cache(outfile,READ_CACHE,0L,0,0))
434 outfile->end_of_file=save_pos;
439 int kill_errno= thd->killed_errno();
440 DBUG_ASSERT(thd->is_error() || kill_errno);
441 my_printf_error(ER_FILSORT_ABORT,
443 MYF(ME_ERROR + ME_WAITTANG),
444 ER_THD(thd, ER_FILSORT_ABORT),
447 thd->get_stmt_da()->message());
449 if (log_warnings > 1)
451 sql_print_warning(
"%s, host: %s, user: %s, thread: %lu, query: %-.4096s",
452 ER_THD(thd, ER_FILSORT_ABORT),
453 thd->security_ctx->host_or_ip,
454 &thd->security_ctx->priv_user[0],
455 (ulong) thd->thread_id,
460 thd->inc_status_sort_rows(num_rows);
461 *examined_rows= param.examined_rows;
462 #ifdef SKIP_DBUG_IN_FILESORT
467 table->sort= table_sort;
470 (
"num_rows: %ld examined_rows: %ld found_rows: %ld",
471 (
long) num_rows, (
long) *examined_rows, (
long) *found_rows));
472 MYSQL_FILESORT_DONE(error, num_rows);
473 DBUG_RETURN(error ? HA_POS_ERROR : num_rows);
477 void filesort_free_buffers(
TABLE *table,
bool full)
479 DBUG_ENTER(
"filesort_free_buffers");
480 my_free(table->sort.record_pointers);
481 table->sort.record_pointers= NULL;
485 table->sort.free_sort_buffer();
486 my_free(table->sort.buffpek);
487 table->sort.buffpek= NULL;
488 table->sort.buffpek_len= 0;
491 my_free(table->sort.addon_buf);
492 my_free(table->sort.addon_field);
493 table->sort.addon_buf= NULL;
494 table->sort.addon_field= NULL;
498 void Filesort::cleanup()
507 uint Filesort::make_sortorder()
510 SORT_FIELD *sort,*pos;
512 DBUG_ENTER(
"make_sortorder");
516 for (ord =
order; ord; ord= ord->next)
519 sortorder= (SORT_FIELD*) sql_alloc(
sizeof(SORT_FIELD) * (count + 1));
525 for (ord=
order; ord; ord= ord->next, pos++)
527 Item *item= ord->item[0]->real_item();
528 pos->field= 0; pos->item= 0;
529 if (item->type() == Item::FIELD_ITEM)
531 else if (item->type() == Item::SUM_FUNC_ITEM && !item->const_item())
532 pos->field= ((
Item_sum*) item)->get_tmp_table_field();
533 else if (item->type() == Item::COPY_STR_ITEM)
535 pos->item= ((
Item_copy*) item)->get_item();
538 pos->item= *ord->item;
539 pos->reverse= (ord->direction == ORDER::ORDER_DESC);
540 DBUG_ASSERT(pos->field != NULL || pos->item != NULL);
556 static uchar *read_buffpek_from_file(
IO_CACHE *buffpek_pointers, uint count,
559 ulong length=
sizeof(
BUFFPEK)*count;
561 DBUG_ENTER(
"read_buffpek_from_file");
562 if (count > UINT_MAX/
sizeof(
BUFFPEK))
565 tmp= (uchar *)my_malloc(length, MYF(MY_WME));
568 if (reinit_io_cache(buffpek_pointers,READ_CACHE,0L,0,0) ||
569 my_b_read(buffpek_pointers, (uchar*) tmp, length))
586 static void dbug_print_record(
TABLE *table,
bool print_rowid)
590 String tmp(buff,
sizeof(buff),&my_charset_bin);
593 fprintf(DBUG_FILE,
"record (");
594 for (pfield= table->field; *pfield ; pfield++)
595 fprintf(DBUG_FILE,
"%s%s", (*pfield)->field_name, (pfield[1])?
", ":
"");
596 fprintf(DBUG_FILE,
") = ");
598 fprintf(DBUG_FILE,
"(");
599 for (pfield= table->field; *pfield ; pfield++)
601 Field *field= *pfield;
603 if (field->is_null())
604 fwrite(
"NULL",
sizeof(
char), 4, DBUG_FILE);
606 if (field->type() == MYSQL_TYPE_BIT)
609 field->val_str(&tmp);
611 fwrite(tmp.ptr(),
sizeof(char),tmp.length(),DBUG_FILE);
613 fwrite(
", ",
sizeof(
char), 2, DBUG_FILE);
615 fprintf(DBUG_FILE,
")");
618 fprintf(DBUG_FILE,
" rowid ");
621 fprintf(DBUG_FILE,
"%x", (uchar)table->file->ref[
i]);
624 fprintf(DBUG_FILE,
"\n");
682 int error,flag,quick_select;
683 uint idx,indexpos,ref_length;
684 uchar *ref_pos,*next_pos,ref_buff[MAX_REFLENGTH];
687 THD *thd= current_thd;
688 volatile THD::killed_state *killed= &thd->killed;
690 MY_BITMAP *save_read_set, *save_write_set;
693 DBUG_ENTER(
"find_all_keys");
694 DBUG_PRINT(
"info",(
"using: %s",
695 (select ? select->quick ?
"ranges" :
"where":
699 error=quick_select=0;
700 sort_form=param->sort_form;
701 file=sort_form->file;
702 ref_length=param->ref_length;
704 quick_select=select && select->quick;
707 flag= ((file->
ha_table_flags() & HA_REC_NOT_IN_SEQ) || quick_select);
709 ref_pos= &file->ref[0];
714 DBUG_EXECUTE_IF(
"bug14365043_1",
715 DBUG_SET(
"+d,ha_rnd_init_fail"););
719 DBUG_RETURN(HA_POS_ERROR);
721 file->extra_opt(HA_EXTRA_CACHE,
722 current_thd->variables.read_buff_size);
727 if (select->quick->reset())
728 DBUG_RETURN(HA_POS_ERROR);
732 save_read_set= sort_form->read_set;
733 save_write_set= sort_form->write_set;
735 bitmap_clear_all(&sort_form->tmp_set);
737 sort_form->read_set= &sort_form->tmp_set;
739 register_used_fields(param);
742 if (select && select->cond)
743 select->cond->walk(&Item::register_field_in_read_map, 1,
747 if (select && select->icp_cond)
748 select->icp_cond->walk(&Item::register_field_in_read_map, 1,
751 sort_form->column_bitmaps_set(&sort_form->tmp_set, &sort_form->tmp_set);
757 if ((error= select->quick->get_next()))
759 file->position(sort_form->record[0]);
760 DBUG_EXECUTE_IF(
"debug_filesort", dbug_print_record(sort_form, TRUE););
768 my_store_ptr(ref_pos,ref_length,record);
769 record+= sort_form->s->db_record_offset;
772 file->position(sort_form->record[0]);
774 if (error && error != HA_ERR_RECORD_DELETED)
780 DBUG_PRINT(
"info",(
"Sort killed by user"));
783 (void) file->extra(HA_EXTRA_NO_CACHE);
786 DBUG_RETURN(HA_POS_ERROR);
789 param->examined_rows++;
790 if (!error && (!select ||
791 (!select->skip_record(thd, &skip_record) && !skip_record)))
801 if (idx == param->max_keys_per_buffer)
803 if (write_keys(param, fs_info, idx, buffpek_pointers, tempfile))
804 DBUG_RETURN(HA_POS_ERROR);
815 else if (!thd->is_error())
823 (void) file->extra(HA_EXTRA_NO_CACHE);
829 DBUG_RETURN(HA_POS_ERROR);
832 sort_form->column_bitmaps_set(save_read_set, save_write_set);
834 DBUG_PRINT(
"test",(
"error: %d indexpos: %d",error,indexpos));
835 if (error != HA_ERR_END_OF_FILE)
837 file->
print_error(error,MYF(ME_ERROR | ME_WAITTANG));
838 DBUG_RETURN(HA_POS_ERROR);
840 if (indexpos && idx &&
841 write_keys(param, fs_info, idx, buffpek_pointers, tempfile))
842 DBUG_RETURN(HA_POS_ERROR);
843 const ha_rows retval=
844 my_b_inited(tempfile) ?
845 (ha_rows) (my_b_tell(tempfile)/param->rec_length) : idx;
846 DBUG_PRINT(
"info", (
"find_all_keys return %u", (uint) retval));
880 DBUG_ENTER(
"write_keys");
882 rec_length= param->rec_length;
883 uchar **sort_keys= fs_info->get_sort_keys();
887 if (!my_b_inited(tempfile) &&
888 open_cached_file(tempfile, mysql_tmpdir, TEMP_PREFIX, DISK_BUFFER_SIZE,
892 if (my_b_tell(buffpek_pointers) +
sizeof(
BUFFPEK) > (ulonglong)UINT_MAX)
894 buffpek.file_pos= my_b_tell(tempfile);
895 if ((ha_rows) count > param->max_rows)
896 count=(uint) param->max_rows;
897 buffpek.count=(ha_rows) count;
898 for (end=sort_keys+count ; sort_keys != end ; sort_keys++)
899 if (my_b_write(tempfile, (uchar*) *sort_keys, (uint) rec_length))
901 if (my_b_write(buffpek_pointers, (uchar*) &buffpek,
sizeof(buffpek)))
914 static inline void store_length(uchar *
to, uint length, uint pack_length)
916 switch (pack_length) {
921 mi_int2store(to, length);
924 mi_int3store(to, length);
927 mi_int4store(to, length);
933 #ifdef WORDS_BIGENDIAN
934 const bool Is_big_endian=
true;
936 const bool Is_big_endian=
false;
938 void copy_native_longlong(uchar *to,
int to_length,
939 longlong val,
bool is_unsigned)
941 copy_integer<Is_big_endian>(
to, to_length,
942 static_cast<uchar*
>(
static_cast<void*
>(&val)),
952 SORT_FIELD *sort_field;
954 for (sort_field= param->local_sortorder ;
955 sort_field != param->end ;
958 bool maybe_null=
false;
959 if (sort_field->field)
961 Field *field= sort_field->field;
962 if (field->maybe_null())
964 if (field->is_null())
966 if (sort_field->reverse)
967 memset(to, 255, sort_field->length+1);
969 memset(to, 0, sort_field->length+1);
970 to+= sort_field->length+1;
980 Item *item=sort_field->item;
981 maybe_null= item->maybe_null;
982 switch (sort_field->result_type) {
986 char fill_char= ((cs->state & MY_CS_BINSORT) ? (
char) 0 :
' ');
988 uint sort_field_length;
993 String tmp((
char*) to,sort_field->length+4,cs);
994 String *res= item->str_result(&tmp);
998 memset(to-1, 0, sort_field->length+1);
1008 DBUG_PRINT(
"warning",
1009 (
"Got null on something that shouldn't be null"));
1010 memset(to, 0, sort_field->length);
1015 uint length= res->length();
1016 sort_field_length= sort_field->length - sort_field->suffix_length;
1017 diff=(int) (sort_field_length - length);
1021 length= sort_field_length;
1023 if (sort_field->suffix_length)
1026 store_length(to + sort_field_length, length,
1027 sort_field->suffix_length);
1029 if (sort_field->need_strxnfrm)
1031 char *from=(
char*) res->ptr();
1033 if ((uchar*) from == to)
1035 set_if_smaller(length,sort_field->length);
1036 memcpy(param->tmp_buffer,from,length);
1037 from=param->tmp_buffer;
1039 tmp_length= cs->coll->strnxfrm(cs, to, sort_field->length,
1040 item->max_char_length(),
1041 (uchar*) from, length,
1042 MY_STRXFRM_PAD_WITH_SPACE |
1043 MY_STRXFRM_PAD_TO_MAXLEN);
1044 DBUG_ASSERT(tmp_length == sort_field->length);
1048 my_strnxfrm(cs,(uchar*)to,length,(
const uchar*)res->ptr(),length);
1049 cs->cset->fill(cs, (
char *)to+length,diff,fill_char);
1055 longlong value= item->field_type() == MYSQL_TYPE_TIME ?
1057 item->is_temporal_with_date() ?
1059 item->val_int_result();
1063 if (item->null_value)
1066 memset(to-1, 0, sort_field->length+1);
1069 DBUG_PRINT(
"warning",
1070 (
"Got null on something that shouldn't be null"));
1071 memset(to, 0, sort_field->length);
1076 copy_native_longlong(to, sort_field->length,
1077 value, item->unsigned_flag);
1080 case DECIMAL_RESULT:
1082 my_decimal dec_buf, *dec_val= item->val_decimal_result(&dec_buf);
1085 if (item->null_value)
1087 memset(to, 0, sort_field->length+1);
1096 my_decimal2binary(E_DEC_FATAL_ERROR, dec_val, buf,
1097 item->max_length - (item->decimals ? 1:0),
1099 memcpy(to, buf, sort_field->length);
1103 my_decimal2binary(E_DEC_FATAL_ERROR, dec_val, to,
1104 item->max_length - (item->decimals ? 1:0),
1111 double value= item->val_result();
1114 if (item->null_value)
1116 memset(to, 0, sort_field->length+1);
1122 if (sort_field->length <
sizeof(
double))
1124 uchar buf[
sizeof(double)];
1125 change_double_for_sort(value, buf);
1126 memcpy(to, buf, sort_field->length);
1130 change_double_for_sort(value, (uchar*) to);
1141 if (sort_field->reverse)
1145 uint length= sort_field->length;
1148 *to = (uchar) (~ *to);
1153 to+= sort_field->length;
1156 if (param->addon_field)
1166 DBUG_ASSERT(addonf != 0);
1167 memset(nulls, 0, addonf->offset);
1168 to+= addonf->offset;
1169 for (
Field* field; (field= addonf->field) ; addonf++)
1171 if (addonf->null_bit && field->is_null())
1173 nulls[addonf->null_offset]|= addonf->null_bit;
1177 (void) field->
pack(to, field->ptr);
1179 to+= addonf->length;
1185 memcpy((uchar*) to, ref_pos, (
size_t) param->ref_length);
1195 static void register_used_fields(
Sort_param *param)
1197 reg1 SORT_FIELD *sort_field;
1198 TABLE *table=param->sort_form;
1201 for (sort_field= param->local_sortorder ;
1202 sort_field != param->end ;
1206 if ((field= sort_field->field))
1208 if (field->table == table)
1209 bitmap_set_bit(bitmap, field->field_index);
1213 sort_field->item->walk(&Item::register_field_in_read_map, 1,
1218 if (param->addon_field)
1222 for ( ; (field= addonf->field) ; addonf++)
1223 bitmap_set_bit(bitmap, field->field_index);
1236 DBUG_ENTER(
"save_index");
1239 res_length= param->res_length;
1240 offset= param->rec_length-res_length;
1241 if (!(to= table_sort->record_pointers=
1242 (uchar*) my_malloc(res_length*count, MYF(MY_WME))))
1244 uchar **sort_keys= table_sort->get_sort_keys();
1245 for (uchar **end= sort_keys+count ; sort_keys != end ; sort_keys++)
1247 memcpy(to, *sort_keys+offset, res_length);
1287 TABLE *table, ha_rows num_rows,
1288 ulong memory_available)
1290 DBUG_ENTER(
"check_if_pq_applicable");
1296 const double PQ_slowness= 3.0;
1299 "filesort_priority_queue_optimization");
1300 if (param->max_rows == HA_POS_ERROR)
1303 .add(
"usable",
false)
1304 .add_alnum(
"cause",
"not applicable (no LIMIT)");
1309 .add(
"limit", param->max_rows)
1310 .add(
"rows_estimate", num_rows)
1311 .add(
"row_size", param->rec_length)
1312 .add(
"memory_available", memory_available);
1314 if (param->max_rows + 2 >= UINT_MAX)
1316 trace_filesort.add(
"usable",
false).add_alnum(
"cause",
"limit too large");
1320 ulong num_available_keys=
1321 memory_available / (param->rec_length +
sizeof(
char*));
1323 param->max_keys_per_buffer= (uint) param->max_rows + 1;
1325 if (num_rows < num_available_keys)
1328 if (param->max_rows < num_rows/PQ_slowness )
1330 filesort_info->alloc_sort_buffer(param->max_keys_per_buffer,
1332 trace_filesort.add(
"chosen",
true);
1333 DBUG_RETURN(filesort_info->get_sort_keys() != NULL);
1338 trace_filesort.add(
"chosen",
false)
1339 .add_alnum(
"cause",
"quicksort_is_cheaper");
1345 if (param->max_keys_per_buffer < num_available_keys)
1347 filesort_info->alloc_sort_buffer(param->max_keys_per_buffer,
1349 trace_filesort.add(
"chosen",
true);
1350 DBUG_RETURN(filesort_info->get_sort_keys() != NULL);
1354 if (param->addon_field)
1356 const ulong row_length=
1357 param->sort_length + param->ref_length +
sizeof(
char*);
1358 num_available_keys= memory_available / row_length;
1361 trace_addon.add(
"row_size", row_length);
1364 if (param->max_keys_per_buffer >= num_available_keys)
1366 trace_addon.add(
"chosen",
false).add_alnum(
"cause",
"not_enough_space");
1370 const double sort_merge_cost=
1371 get_merge_many_buffs_cost_fast(num_rows,
1374 trace_addon.add(
"sort_merge_cost", sort_merge_cost);
1384 const double pq_cpu_cost=
1385 (PQ_slowness * num_rows + param->max_keys_per_buffer) *
1387 const double pq_io_cost=
1388 param->max_rows * table->file->scan_time() / 2.0;
1389 const double pq_cost= pq_cpu_cost + pq_io_cost;
1390 trace_addon.add(
"priority_queue_cost", pq_cost);
1392 if (sort_merge_cost < pq_cost)
1394 trace_addon.add(
"chosen",
false);
1398 trace_addon.add(
"chosen",
true);
1399 filesort_info->alloc_sort_buffer(param->max_keys_per_buffer,
1400 param->sort_length + param->ref_length);
1401 if (filesort_info->get_sort_keys())
1404 my_free(filesort_info->addon_buf);
1405 my_free(filesort_info->addon_field);
1406 filesort_info->addon_buf= NULL;
1407 filesort_info->addon_field= NULL;
1408 param->addon_field= NULL;
1409 param->addon_length= 0;
1411 param->res_length= param->ref_length;
1412 param->sort_length+= param->ref_length;
1413 param->rec_length= param->sort_length;
1431 DBUG_ENTER(
"merge_many_buff");
1433 if (*maxbuffer < MERGEBUFF2)
1435 if (flush_io_cache(t_file) ||
1436 open_cached_file(&t_file2,mysql_tmpdir,TEMP_PREFIX,DISK_BUFFER_SIZE,
1440 from_file= t_file ; to_file= &t_file2;
1441 while (*maxbuffer >= MERGEBUFF2)
1443 if (reinit_io_cache(from_file,READ_CACHE,0L,0,0))
1445 if (reinit_io_cache(to_file,WRITE_CACHE,0L,0,0))
1448 for (i=0 ; i <= *maxbuffer-MERGEBUFF*3/2 ; i+=MERGEBUFF)
1450 if (
merge_buffers(param,from_file,to_file,sort_buffer,lastbuff++,
1451 buffpek+i,buffpek+i+MERGEBUFF-1,0))
1454 if (
merge_buffers(param,from_file,to_file,sort_buffer,lastbuff++,
1455 buffpek+i,buffpek+ *maxbuffer,0))
1457 if (flush_io_cache(to_file))
1459 temp=from_file; from_file=to_file; to_file=
temp;
1460 setup_io_cache(from_file);
1461 setup_io_cache(to_file);
1462 *maxbuffer= (uint) (lastbuff-buffpek)-1;
1465 close_cached_file(to_file);
1466 if (to_file == t_file)
1469 setup_io_cache(t_file);
1472 DBUG_RETURN(*maxbuffer >= MERGEBUFF2);
1486 register uint count;
1489 if ((count=(uint) min((ha_rows) buffpek->max_keys,buffpek->count)))
1492 (length= rec_length*count),
1493 buffpek->file_pos, MYF_RW))
1495 buffpek->key=buffpek->base;
1496 buffpek->file_pos+= length;
1497 buffpek->count-= count;
1498 buffpek->mem_count= count;
1500 return (count*rec_length);
1517 uchar *reuse_end= reuse->base + reuse->max_keys * key_length;
1518 for (uint
i= 0;
i < queue->elements; ++
i)
1521 if (bp->base + bp->max_keys * key_length == reuse->base)
1523 bp->max_keys+= reuse->max_keys;
1526 else if (bp->base == reuse_end)
1528 bp->base= reuse->base;
1529 bp->max_keys+= reuse->max_keys;
1556 IO_CACHE *to_file, uchar *sort_buffer,
1561 uint rec_length,res_length,
offset;
1564 ha_rows max_rows,org_max_rows;
1565 my_off_t to_start_filepos;
1570 void *first_cmp_arg;
1571 volatile THD::killed_state *killed= ¤t_thd->killed;
1572 THD::killed_state not_killable;
1573 DBUG_ENTER(
"merge_buffers");
1575 current_thd->inc_status_sort_merge_passes();
1576 if (param->not_killable)
1578 killed= ¬_killable;
1579 not_killable= THD::NOT_KILLED;
1583 rec_length= param->rec_length;
1584 res_length= param->res_length;
1585 sort_length= param->sort_length;
1586 offset= rec_length-res_length;
1587 maxcount= (ulong) (param->max_keys_per_buffer / ((uint) (Tb-Fb) +1));
1588 to_start_filepos= my_b_tell(to_file);
1589 strpos= (uchar*) sort_buffer;
1590 org_max_rows=max_rows= param->max_rows;
1593 DBUG_ASSERT(maxcount!=0);
1595 if (param->unique_buff)
1597 cmp= param->compare;
1598 first_cmp_arg= (
void *) ¶m->cmp_context;
1602 cmp= get_ptr_compare(sort_length);
1603 first_cmp_arg= (
void*) &sort_length;
1605 if (init_queue(&queue, (uint) (Tb-Fb)+1, offsetof(
BUFFPEK,key), 0,
1606 (queue_compare) cmp, first_cmp_arg))
1608 for (buffpek= Fb ; buffpek <= Tb ; buffpek++)
1610 buffpek->base= strpos;
1611 buffpek->max_keys= maxcount;
1613 (uint) (error= (
int)
read_to_buffer(from_file, buffpek, rec_length));
1616 buffpek->max_keys= buffpek->mem_count;
1617 queue_insert(&queue, (uchar*) buffpek);
1620 if (param->unique_buff)
1630 buffpek= (
BUFFPEK*) queue_top(&queue);
1631 memcpy(param->unique_buff, buffpek->key, rec_length);
1632 if (my_b_write(to_file, (uchar*) buffpek->key, rec_length))
1636 buffpek->key+= rec_length;
1637 buffpek->mem_count--;
1643 queue_replaced(&queue);
1648 while (queue.elements > 1)
1656 buffpek= (
BUFFPEK*) queue_top(&queue);
1659 if (!(*cmp)(first_cmp_arg, &(param->unique_buff),
1660 (uchar**) &buffpek->key))
1661 goto skip_duplicate;
1662 memcpy(param->unique_buff, (uchar*) buffpek->key, rec_length);
1666 if (my_b_write(to_file,(uchar*) buffpek->key, rec_length))
1673 if (my_b_write(to_file, (uchar*) buffpek->key+offset, res_length))
1685 buffpek->key+= rec_length;
1686 if (! --buffpek->mem_count)
1691 (void) queue_remove(&queue,0);
1695 else if (error == -1)
1698 queue_replaced(&queue);
1701 buffpek= (
BUFFPEK*) queue_top(&queue);
1702 buffpek->base= sort_buffer;
1703 buffpek->max_keys= param->max_keys_per_buffer;
1711 if (!(*cmp)(first_cmp_arg, &(param->unique_buff), (uchar**) &buffpek->key))
1713 buffpek->key+= rec_length;
1714 --buffpek->mem_count;
1720 if ((ha_rows) buffpek->mem_count > max_rows)
1722 buffpek->mem_count= (uint) max_rows;
1725 max_rows-= buffpek->mem_count;
1728 if (my_b_write(to_file,(uchar*) buffpek->key,
1729 (rec_length*buffpek->mem_count)))
1736 register uchar *end;
1737 strpos= buffpek->key+
offset;
1738 for (end= strpos+buffpek->mem_count*rec_length ;
1740 strpos+= rec_length)
1742 if (my_b_write(to_file, (uchar *) strpos, res_length))
1749 while ((error=(
int)
read_to_buffer(from_file,buffpek, rec_length))
1750 != -1 && error != 0);
1753 lastbuff->count= min(org_max_rows-max_rows, param->max_rows);
1754 lastbuff->file_pos= to_start_filepos;
1756 delete_queue(&queue);
1763 static int merge_index(
Sort_param *param, uchar *sort_buffer,
1764 BUFFPEK *buffpek, uint maxbuffer,
1767 DBUG_ENTER(
"merge_index");
1768 if (
merge_buffers(param,tempfile,outfile,sort_buffer,buffpek,buffpek,
1769 buffpek+maxbuffer,1))
1775 static uint suffix_length(ulong string_length)
1777 if (string_length < 256)
1779 if (string_length < 256L*256L)
1781 if (string_length < 256L*256L*256L)
1808 bool *multi_byte_charset)
1810 uint total_length= 0;
1812 *multi_byte_charset=
false;
1814 for (; s_length-- ; sortorder++)
1816 sortorder->need_strxnfrm= 0;
1817 sortorder->suffix_length= 0;
1818 if (sortorder->field)
1820 cs= sortorder->field->sort_charset();
1821 sortorder->length= sortorder->field->sort_length();
1823 if (use_strnxfrm((cs=sortorder->field->sort_charset())))
1825 sortorder->need_strxnfrm= 1;
1826 *multi_byte_charset= 1;
1827 sortorder->length= cs->coll->strnxfrmlen(cs, sortorder->length);
1829 if (sortorder->field->maybe_null())
1832 if (sortorder->field->result_type() == STRING_RESULT &&
1833 !sortorder->field->is_temporal())
1835 set_if_smaller(sortorder->length, thd->variables.max_sort_length);
1840 sortorder->result_type= sortorder->item->result_type();
1841 if (sortorder->item->is_temporal())
1842 sortorder->result_type= INT_RESULT;
1843 switch (sortorder->result_type) {
1845 sortorder->length= sortorder->item->max_length;
1846 set_if_smaller(sortorder->length, thd->variables.max_sort_length);
1847 if (use_strnxfrm((cs=sortorder->item->collation.collation)))
1849 sortorder->length= cs->coll->strnxfrmlen(cs, sortorder->length);
1850 sortorder->need_strxnfrm= 1;
1851 *multi_byte_charset= 1;
1853 else if (cs == &my_charset_bin)
1856 sortorder->suffix_length= suffix_length(sortorder->length);
1857 sortorder->length+= sortorder->suffix_length;
1861 #if SIZEOF_LONG_LONG > 4
1862 sortorder->length=8;
1864 sortorder->length=4;
1867 case DECIMAL_RESULT:
1869 my_decimal_get_binary_size(sortorder->item->max_length -
1870 (sortorder->item->decimals ? 1 : 0),
1871 sortorder->item->decimals);
1874 sortorder->length=
sizeof(double);
1882 if (sortorder->item->maybe_null)
1885 total_length+= sortorder->length;
1887 sortorder->field= NULL;
1888 DBUG_PRINT(
"info",(
"sort_length: %u", total_length));
1889 return total_length;
1921 get_addon_fields(ulong max_length_for_sort_data,
1929 uint null_fields= 0;
1930 MY_BITMAP *read_set= (*ptabfield)->table->read_set;
1943 for (pfield= ptabfield; (field= *pfield) ; pfield++)
1945 if (!bitmap_is_set(read_set, field->field_index))
1947 if (field->flags & BLOB_FLAG)
1949 length+= field->max_packed_col_length(field->pack_length());
1950 if (field->maybe_null())
1956 length+= (null_fields+7)/8;
1958 if (length+sortlength > max_length_for_sort_data ||
1960 (fields+1), MYF(MY_WME))))
1964 length= (null_fields+7)/8;
1966 for (pfield= ptabfield; (field= *pfield) ; pfield++)
1968 if (!bitmap_is_set(read_set, field->field_index))
1970 addonf->field= field;
1971 addonf->offset= length;
1972 if (field->maybe_null())
1974 addonf->null_offset= null_fields/8;
1975 addonf->null_bit= 1<<(null_fields & 7);
1980 addonf->null_offset= 0;
1981 addonf->null_bit= 0;
1983 addonf->length= field->max_packed_col_length(field->pack_length());
1984 length+= addonf->length;
1989 DBUG_PRINT(
"info",(
"addon_length: %d",length));
1990 return (addonf-fields);
2015 for ( ; (field= addonf->field) ; addonf++)
2017 if (addonf->null_bit && (addonf->null_bit & buff[addonf->null_offset]))
2022 field->set_notnull();
2023 field->
unpack(field->ptr, buff + addonf->offset);
2032 #define DBL_EXP_DIG (sizeof(double)*8-DBL_MANT_DIG)
2034 void change_double_for_sort(
double nr,uchar *to)
2036 uchar *tmp=(uchar*) to;
2040 memset(tmp+1, 0,
sizeof(nr)-1);
2044 #ifdef WORDS_BIGENDIAN
2045 memcpy(tmp, &nr,
sizeof(nr));
2048 uchar *ptr= (uchar*) &nr;
2049 #if defined(__FLOAT_WORD_ORDER) && (__FLOAT_WORD_ORDER == __BIG_ENDIAN)
2050 tmp[0]= ptr[3]; tmp[1]=ptr[2]; tmp[2]= ptr[1]; tmp[3]=ptr[0];
2051 tmp[4]= ptr[7]; tmp[5]=ptr[6]; tmp[6]= ptr[5]; tmp[7]=ptr[4];
2053 tmp[0]= ptr[7]; tmp[1]=ptr[6]; tmp[2]= ptr[5]; tmp[3]=ptr[4];
2054 tmp[4]= ptr[3]; tmp[5]=ptr[2]; tmp[6]= ptr[1]; tmp[7]=ptr[0];
2061 for (i=0 ; i <
sizeof(nr); i++)
2062 tmp[i]=tmp[i] ^ (uchar) 255;
2066 ushort exp_part=(((ushort) tmp[0] << 8) | (ushort) tmp[1] |
2068 exp_part+= (ushort) 1 << (16-1-DBL_EXP_DIG);
2069 tmp[0]= (uchar) (exp_part >> 8);
2070 tmp[1]= (uchar) exp_part;