--- ../mysql-5.1.24-rc-x86_64-debug/include/my_sys.h 2008-04-08 20:23:23.000000000 +0900 +++ include/my_sys.h 2008-06-19 20:12:17.000000000 +0900 @@ -725,9 +725,10 @@ extern void handle_recived_signals(void); extern sig_handler my_set_alarm_variable(int signo); -extern void my_string_ptr_sort(uchar *base,uint items,size_t size); +extern void my_string_ptr_sort(uchar *base,uint items,size_t size,size_t sort_offset,size_t sort_size); extern void radixsort_for_str_ptr(uchar* base[], uint number_of_elements, - size_t size_of_element,uchar *buffer[]); + size_t size_of_element,size_t sort_offset, + size_t size_of_sort_data,uchar *buffer[]); extern qsort_t my_qsort(void *base_ptr, size_t total_elems, size_t size, qsort_cmp cmp); extern qsort_t my_qsort2(void *base_ptr, size_t total_elems, size_t size, --- ../mysql-5.1.24-rc-x86_64-debug/mysys/mf_qsort.c 2008-04-08 20:23:02.000000000 +0900 +++ mysys/mf_qsort.c 2008-06-20 15:06:48.000000000 +0900 @@ -26,7 +26,11 @@ #endif /* We need to use qsort with 2 different compare functions */ -#ifdef QSORT_EXTRA_CMP_ARGUMENT +#ifdef QSORT_PTR_MEMCMP_FIXED +#define CMP(A,B) memcmp_fixed(*(uchar**)(A),*(uchar**)(B),QSORT_PTR_MEMCMP_FIXED) +#elif defined(QSORT_PTR_MEMCMP) +#define CMP(A,B) memcmp(*(uchar**)(A),*(uchar**)(B),cmp_size) +#elif defined(QSORT_EXTRA_CMP_ARGUMENT) #define CMP(A,B) ((*cmp)(cmp_argument,(A),(B))) #else #define CMP(A,B) ((*cmp)((A),(B))) @@ -63,10 +67,13 @@ /* The following node is used to store ranges to avoid recursive calls */ +#ifndef MF_QSORT_ST_STACK_DEFINED +#define MF_QSORT_ST_STACK_DEFINED typedef struct st_stack { char *low,*high; } stack_node; +#endif #define PUSH(LOW,HIGH) {stack_ptr->low = LOW; stack_ptr++->high = HIGH;} #define POP(LOW,HIGH) {LOW = (--stack_ptr)->low; HIGH = stack_ptr->high;} @@ -90,13 +97,20 @@ ** Use median comparison to find partition element *****************************************************************************/ -#ifdef QSORT_EXTRA_CMP_ARGUMENT +#ifdef QSORT_PTR_MEMCMP_FIXED +__inline qsort_t QSORT_PTR_MEMCMP_FIXED_FUNC(void *base_ptr, size_t count) +#elif defined(QSORT_PTR_MEMCMP) +__inline qsort_t my_qsort_ptr_memcmp(void *base_ptr, size_t count, size_t cmp_size) +#elif defined(QSORT_EXTRA_CMP_ARGUMENT) qsort_t my_qsort2(void *base_ptr, size_t count, size_t size, qsort2_cmp cmp, void *cmp_argument) #else qsort_t my_qsort(void *base_ptr, size_t count, size_t size, qsort_cmp cmp) #endif { +#if defined(QSORT_PTR_MEMCMP) || defined(QSORT_PTR_MEMCMP_FIXED) + const size_t size = sizeof(uchar*); +#endif char *low, *high, *pivot; stack_node stack[STACK_SIZE], *stack_ptr; my_bool ptr_cmp; @@ -214,3 +228,12 @@ my_afree(pivot); SORT_RETURN; } + +#undef CMP +#undef SWAP +#undef MEDIAN +#undef PUSH +#undef POP +#undef STACK_SIZE +#undef THRESHOLD_FOR_INSERT_SORT +#undef SORT_RETURN --- ../mysql-5.1.24-rc-x86_64-debug/mysys/mf_radix.c 2008-04-08 20:23:02.000000000 +0900 +++ mysys/mf_radix.c 2008-06-19 21:53:23.000000000 +0900 @@ -25,15 +25,16 @@ /* Radixsort */ -void radixsort_for_str_ptr(uchar **base, uint number_of_elements, size_t size_of_element, uchar **buffer) +void radixsort_for_str_ptr(uchar **base, uint number_of_elements, size_t size_of_element, size_t sort_offset, size_t size_of_sort_data, uchar **buffer) { uchar **end,**ptr,**buffer_ptr; uint32 *count_ptr,*count_end,count[256]; - int pass; + int pass, swapcnt = 0; - end=base+number_of_elements; count_end=count+256; - for (pass=(int) size_of_element-1 ; pass >= 0 ; pass--) + count_end= count+256; + for (pass=(int) size_of_sort_data+sort_offset-1; pass >= (int)sort_offset; pass--) { + end= base + number_of_elements; bzero((uchar*) count,sizeof(uint32)*256); for (ptr= base ; ptr < end ; ptr++) count[ptr[0][pass]]++; @@ -47,8 +48,11 @@ } for (ptr= end ; ptr-- != base ;) buffer[--count[ptr[0][pass]]]= *ptr; - for (ptr=base, buffer_ptr=buffer ; ptr < end ;) - (*ptr++) = *buffer_ptr++; + swap_variables(uchar**, base, buffer); + swapcnt++; next:; } + + if (swapcnt & 1) + memcpy(buffer, base, number_of_elements * sizeof(uchar*)); } --- ../mysql-5.1.24-rc-x86_64-debug/mysys/mf_sort.c 2008-04-08 20:23:23.000000000 +0900 +++ mysys/mf_sort.c 2008-06-20 15:07:08.000000000 +0900 @@ -18,7 +18,125 @@ #include "mysys_priv.h" #include -void my_string_ptr_sort(uchar *base, uint items, size_t size) + +__inline int memcmp_fixed(const void *va, const void *vb, size_t n) +{ + const uchar *a = va, *b = vb; + while (n >= 4) { + if (*(unsigned*)a != *(unsigned*)b) + return (longlong)ntohl(*(unsigned*)a) - (longlong)ntohl(*(unsigned*)b); + a += 4, b += 4, n -= 4; + } + while (n != 0) { + if (*a != *b) + return (int)*a - (int)*b; + a += 1, b += 1, n -= 1; + } + return 0; +} + +#define QSORT_PTR_MEMCMP_FIXED_FUNC my_qsort_ptr_memcmp1 +#define QSORT_PTR_MEMCMP_FIXED 1 +#include "mf_qsort.c" +#undef QSORT_PTR_MEMCMP_FIXED_FUNC +#undef QSORT_PTR_MEMCMP_FIXED + +#define QSORT_PTR_MEMCMP_FIXED_FUNC my_qsort_ptr_memcmp2 +#define QSORT_PTR_MEMCMP_FIXED 2 +#include "mf_qsort.c" +#undef QSORT_PTR_MEMCMP_FIXED_FUNC +#undef QSORT_PTR_MEMCMP_FIXED + +#define QSORT_PTR_MEMCMP_FIXED_FUNC my_qsort_ptr_memcmp3 +#define QSORT_PTR_MEMCMP_FIXED 3 +#include "mf_qsort.c" +#undef QSORT_PTR_MEMCMP_FIXED_FUNC +#undef QSORT_PTR_MEMCMP_FIXED + +#define QSORT_PTR_MEMCMP_FIXED_FUNC my_qsort_ptr_memcmp4 +#define QSORT_PTR_MEMCMP_FIXED 4 +#include "mf_qsort.c" +#undef QSORT_PTR_MEMCMP_FIXED_FUNC +#undef QSORT_PTR_MEMCMP_FIXED + +#define QSORT_PTR_MEMCMP_FIXED_FUNC my_qsort_ptr_memcmp5 +#define QSORT_PTR_MEMCMP_FIXED 5 +#include "mf_qsort.c" +#undef QSORT_PTR_MEMCMP_FIXED_FUNC +#undef QSORT_PTR_MEMCMP_FIXED + +#define QSORT_PTR_MEMCMP_FIXED_FUNC my_qsort_ptr_memcmp6 +#define QSORT_PTR_MEMCMP_FIXED 6 +#include "mf_qsort.c" +#undef QSORT_PTR_MEMCMP_FIXED_FUNC +#undef QSORT_PTR_MEMCMP_FIXED + +#define QSORT_PTR_MEMCMP_FIXED_FUNC my_qsort_ptr_memcmp7 +#define QSORT_PTR_MEMCMP_FIXED 7 +#include "mf_qsort.c" +#undef QSORT_PTR_MEMCMP_FIXED_FUNC +#undef QSORT_PTR_MEMCMP_FIXED + +#define QSORT_PTR_MEMCMP_FIXED_FUNC my_qsort_ptr_memcmp8 +#define QSORT_PTR_MEMCMP_FIXED 8 +#include "mf_qsort.c" +#undef QSORT_PTR_MEMCMP_FIXED_FUNC +#undef QSORT_PTR_MEMCMP_FIXED + +#define QSORT_PTR_MEMCMP_FIXED_FUNC my_qsort_ptr_memcmp9 +#define QSORT_PTR_MEMCMP_FIXED 9 +#include "mf_qsort.c" +#undef QSORT_PTR_MEMCMP_FIXED_FUNC +#undef QSORT_PTR_MEMCMP_FIXED + +#define QSORT_PTR_MEMCMP_FIXED_FUNC my_qsort_ptr_memcmp10 +#define QSORT_PTR_MEMCMP_FIXED 10 +#include "mf_qsort.c" +#undef QSORT_PTR_MEMCMP_FIXED_FUNC +#undef QSORT_PTR_MEMCMP_FIXED + +#define QSORT_PTR_MEMCMP_FIXED_FUNC my_qsort_ptr_memcmp11 +#define QSORT_PTR_MEMCMP_FIXED 11 +#include "mf_qsort.c" +#undef QSORT_PTR_MEMCMP_FIXED_FUNC +#undef QSORT_PTR_MEMCMP_FIXED + +#define QSORT_PTR_MEMCMP_FIXED_FUNC my_qsort_ptr_memcmp12 +#define QSORT_PTR_MEMCMP_FIXED 12 +#include "mf_qsort.c" +#undef QSORT_PTR_MEMCMP_FIXED_FUNC +#undef QSORT_PTR_MEMCMP_FIXED + +#define QSORT_PTR_MEMCMP_FIXED_FUNC my_qsort_ptr_memcmp13 +#define QSORT_PTR_MEMCMP_FIXED 13 +#include "mf_qsort.c" +#undef QSORT_PTR_MEMCMP_FIXED_FUNC +#undef QSORT_PTR_MEMCMP_FIXED + +#define QSORT_PTR_MEMCMP_FIXED_FUNC my_qsort_ptr_memcmp14 +#define QSORT_PTR_MEMCMP_FIXED 14 +#include "mf_qsort.c" +#undef QSORT_PTR_MEMCMP_FIXED_FUNC +#undef QSORT_PTR_MEMCMP_FIXED + +#define QSORT_PTR_MEMCMP_FIXED_FUNC my_qsort_ptr_memcmp15 +#define QSORT_PTR_MEMCMP_FIXED 15 +#include "mf_qsort.c" +#undef QSORT_PTR_MEMCMP_FIXED_FUNC +#undef QSORT_PTR_MEMCMP_FIXED + +#define QSORT_PTR_MEMCMP_FIXED_FUNC my_qsort_ptr_memcmp16 +#define QSORT_PTR_MEMCMP_FIXED 16 +#include "mf_qsort.c" +#undef QSORT_PTR_MEMCMP_FIXED_FUNC +#undef QSORT_PTR_MEMCMP_FIXED + +#define QSORT_PTR_MEMCMP +#include "mf_qsort.c" +#undef QSORT_PTR_MEMCMP + +void my_string_ptr_sort(uchar *base, uint items, size_t size, + size_t sort_offset, size_t sort_size) { #if INT_MAX > 65536L uchar **ptr=0; @@ -26,16 +144,32 @@ if (size <= 20 && items >= 1000 && items < 100000 && (ptr= (uchar**) my_malloc(items*sizeof(char*),MYF(0)))) { - radixsort_for_str_ptr((uchar**) base,items,size,ptr); + radixsort_for_str_ptr((uchar**) base,items,size,sort_offset,sort_size,ptr); my_free((uchar*) ptr,MYF(0)); } else #endif - { - if (size && items) - { - my_qsort2(base,items, sizeof(uchar*), get_ptr_compare(size), - (void*) &size); + if (items) { + switch (size) { +#define FIXEDSZ(n) case n: my_qsort_ptr_memcmp##n(base, items); break + FIXEDSZ(1); + FIXEDSZ(2); + FIXEDSZ(3); + FIXEDSZ(4); + FIXEDSZ(5); + FIXEDSZ(6); + FIXEDSZ(7); + FIXEDSZ(8); + FIXEDSZ(9); + FIXEDSZ(10); + FIXEDSZ(11); + FIXEDSZ(12); + FIXEDSZ(13); + FIXEDSZ(14); + FIXEDSZ(15); + FIXEDSZ(16); + default: + my_qsort_ptr_memcmp(base, items, size); break; } } } --- ../mysql-5.1.24-rc-x86_64-debug/sql/filesort.cc 2008-04-08 20:23:11.000000000 +0900 +++ sql/filesort.cc 2008-06-20 08:42:18.000000000 +0900 @@ -410,6 +410,16 @@ DBUG_RETURN(tmp); } +static void calc_sort_offset(SORTPARAM *param, ulonglong minmax_xor) +{ + param->sort_offset= 0; + for (int s= 56; s >= 0; s-= 8) { + if ((uchar)(minmax_xor >> s) != 0) + break; + param->sort_offset++; + } + param->sort_offset= min(param->sort_offset, param->sort_length); +} /** Search after sort_keys and write them into tempfile. @@ -462,6 +472,8 @@ volatile THD::killed_state *killed= &thd->killed; handler *file; MY_BITMAP *save_read_set, *save_write_set; + ulonglong first8_min= 0, first8_max= 0; + bool first8_inited= false; DBUG_ENTER("find_all_keys"); DBUG_PRINT("info",("using: %s", (select ? select->quick ? "ranges" : "where": @@ -563,12 +575,36 @@ { if (idx == param->keys) { + if (first8_inited) + calc_sort_offset(param, first8_min ^ first8_max); if (write_keys(param,sort_keys,idx,buffpek_pointers,tempfile)) DBUG_RETURN(HA_POS_ERROR); idx=0; indexpos++; + first8_inited= false; + } + uchar *buf= sort_keys[idx]; + make_sortkey(param,buf,ref_pos); + ulonglong first8= 0; + switch (param->sort_length) { + default: first8|= (ulonglong)buf[7]; + case 7: first8|= (ulonglong)buf[6] << 8; + case 6: first8|= (ulonglong)buf[5] << 16; + case 5: first8|= (ulonglong)buf[4] << 24; + case 4: first8|= (ulonglong)buf[3] << 32; + case 3: first8|= (ulonglong)buf[2] << 40; + case 2: first8|= (ulonglong)buf[1] << 48; + case 1: first8|= (ulonglong)buf[0] << 56; + case 0: break; + } + if (!first8_inited) { + first8_min= first8_max = first8; + first8_inited= true; + } else { + first8_min= min(first8_min, first8); + first8_max= max(first8_max, first8); } - make_sortkey(param,sort_keys[idx++],ref_pos); + idx++; } else file->unlock_row(); @@ -576,6 +612,8 @@ if (thd->is_error()) break; } + if (first8_inited) + calc_sort_offset(param, first8_min ^ first8_max); if (quick_select) { /* @@ -648,7 +686,10 @@ #ifdef MC68000 quicksort(sort_keys,count,sort_length); #else - my_string_ptr_sort((uchar*) sort_keys, (uint) count, sort_length); + my_string_ptr_sort((uchar*) sort_keys, (uint) count, sort_length, + param->sort_offset, + (param->addon_field ? sort_length : + sort_length - param->ref_length) - param->sort_offset); #endif if (!my_b_inited(tempfile) && open_cached_file(tempfile, mysql_tmpdir, TEMP_PREFIX, DISK_BUFFER_SIZE, @@ -993,7 +1034,11 @@ uchar *to; DBUG_ENTER("save_index"); - my_string_ptr_sort((uchar*) sort_keys, (uint) count, param->sort_length); + my_string_ptr_sort((uchar*) sort_keys, (uint) count, param->sort_length, + param->sort_offset, + (param->addon_field ? param->sort_length : + param->sort_length - param->ref_length) + - param->sort_offset); res_length= param->res_length; offset= param->rec_length-res_length; if ((ha_rows) count > param->max_rows) --- ../mysql-5.1.24-rc-x86_64-debug/sql/sql_sort.h 2008-04-08 20:23:11.000000000 +0900 +++ sql/sql_sort.h 2008-06-19 20:00:14.000000000 +0900 @@ -59,6 +59,7 @@ typedef struct st_sort_param { uint rec_length; /* Length of sorted records */ uint sort_length; /* Length of sorted columns */ + uint sort_offset; /* Offset of sorted columns */ uint ref_length; /* Length of record ref. */ uint addon_length; /* Length of added packed fields */ uint res_length; /* Length of records in final sorted file/buffer */