MYSQL INNODB主键使用varchar和int的区别(2)

2、innodb varchar类型比较
实际上这个比较会通过cmp_data->cmp_whole_field->my_strnncollsp_simple调用最终调用
my_strnncollsp_simple完成,而比如order by 会调用my_strnxfrm_simple他们都在一个
文件中。
下面是整个my_strnncollsp_simple函数

/*

Compare strings, discarding end space


  SYNOPSIS
    my_strnncollsp_simple()
    cs    character set handler
    a    First string to compare
    a_length    Length of 'a'
    b    Second string to compare
    b_length    Length of 'b'
    diff_if_only_endspace_difference
      Set to 1 if the strings should be regarded as different
                        if they only difference in end space


  IMPLEMENTATION
    If one string is shorter as the other, then we space extend the other
    so that the strings have equal length.


    This will ensure that the following things hold:


    "a" == "a "
    "a\0" < "a"
    "a\0" < "a "


  RETURN
    < 0    a < b
    = 0    a == b
    > 0    a > b
*/


int my_strnncollsp_simple(const CHARSET_INFO *cs, const uchar *a,
                          size_t a_length, const uchar *b, size_t b_length,
                          my_bool diff_if_only_endspace_difference)
{
  const uchar *map= cs->sort_order, *end;
  size_t length;
  int res;


#ifndef VARCHAR_WITH_DIFF_ENDSPACE_ARE_DIFFERENT_FOR_UNIQUE
  diff_if_only_endspace_difference= 0;
#endif


  end= a + (length= MY_MIN(a_length, b_length));
  while (a < end)
  {
    if (map[*a++] != map[*b++])
      return ((int) map[a[-1]] - (int) map[b[-1]]);
  }
  res= 0;
  if (a_length != b_length)
  {
    int swap= 1;
    if (diff_if_only_endspace_difference)
      res= 1; /* Assume 'a' is bigger */
    /*
      Check the next not space character of the longer key. If it's < ' ',
      then it's smaller than the other key.
    */
    if (a_length < b_length)
    {
      /* put shorter key in s */
      a_length= b_length;
      a= b;
      swap= -1; /* swap sign of result */
      res= -res;
    }
    for (end= a + a_length-length; a < end ; a++)
    {
      if (map[*a] != map[' '])
return (map[*a] < map[' ']) ? -swap : swap;
    }
  }
  return res;
}
其中*map= cs->sort_order比较关键这是内存中已经存储好的字符集的顺序,
循环进行
map[*a++] != map[*b++]
*a++和*b++ 会得到的字符集编码,然后在整个排序好的字符数组中找,
则得到了实际字符集编码进行比较,不管是比较的复杂度还是需要比较的
长度 varchar很可能都远远大于int类型,下面是打印cs->sort_order这片
内存区域前128字节得到的结果,
(gdb) x/128bx 0x258b000
0x258b000 :          0x00    0x01    0x02    0x03    0x04    0x05    0x06    0x07
0x258b008 :        0x08    0x09    0x0a    0x0b    0x0c    0x0d    0x0e    0x0f
0x258b010 :      0x10    0x11    0x12    0x13    0x14    0x15    0x16    0x17
0x258b018 :      0x18    0x19    0x1a    0x1b    0x1c    0x1d    0x1e    0x1f
0x258b020 :      0x20    0x21    0x22    0x23    0x24    0x25    0x26    0x27
0x258b028 :      0x28    0x29    0x2a    0x2b    0x2c    0x2d    0x2e    0x2f
0x258b030 :      0x30    0x31    0x32    0x33    0x34    0x35    0x36    0x37
0x258b038 :      0x38    0x39    0x3a    0x3b    0x3c    0x3d    0x3e    0x3f
0x258b040 :      0x40    0x41    0x42    0x43    0x44    0x45    0x46    0x47
0x258b048 :      0x48    0x49    0x4a    0x4b    0x4c    0x4d    0x4e    0x4f
0x258b050 :      0x50    0x51    0x52    0x53    0x54    0x55    0x56    0x57
0x258b058 :      0x58    0x59    0x5a    0x5b    0x5c    0x5d    0x5e    0x5f
0x258b060 :      0x60    0x41    0x42    0x43    0x44    0x45    0x46    0x47
0x258b068 :      0x48    0x49    0x4a    0x4b    0x4c    0x4d    0x4e    0x4f
0x258b070 :      0x50    0x51    0x52    0x53    0x54    0x55    0x56    0x57
0x258b078 :      0x58    0x59    0x5a    0x7b    0x7c    0x7d    0x7e    0x7f
而从内存的地址0x258b000我们也能看到他确实是存在于堆内存空间中,它是一片堆内存区域。

下面是varchar比较的调用栈帧以备后用

#0 my_strnncollsp_simple (cs=0x2d4b9c0, a=0x7fff57a71f93 "gaopeng", a_length=7, b=0x7fffbd7e807f "gaopeng", b_length=7, diff_if_only_endspace_difference=0 '\000')

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/edf62bd527028f7eb7f5fa156abb0d27.html