MyISAM storage engine has key compression which makes its indexes much smaller, allowing better fit in caches and so improving performance dramatically. Actually packed indexes not a bit longer rows is frequent reason of MyISAM performing better than Innodb. In this article I’ll get in a bit more details about packed keys and performance implications it causes.

First lets see how key compression works. Key compression applies on the block boundaries – first index value is stored fully while for following value index will contain value of the bytes sames as in previous cases + the all bytes which are different. So lets say you have page starting with index values “aaaaaa” and “aaaaab”. They will be encoded as “aaaaaa”, “<5>b”. The similar compression applies to data pointer for the same key value. It also can be used for numbers as numbers stored with high byte first. This is obviously a bit of simplification but it should be enough to understand performance implications of this approach.

Note trailing spaces for strings are not stored in the index even if it is not packed.

Compressed blocks need to be treated differently. For uncompressed index blocks MySQL can do binary search inside the page – kind of jumping in the middle and looking at the key value and repeating it then repeating it for left or right half. For compressed block this is not going to work and MySQL will need to scan keyblock from the start uncompressing keys to find matching key value. This means the following will apply:

  • Forward range/index scan will be fast (read_next) as MyISAM will remember previous position and will not uncompress block from the start to retrieve next value
  • Reverse range/index scan will be slower (read_prev) as MyISAM will have to start bock uncompressing over to get previous value
  • Random single row lookup by index (ie joins) will also suffer as key block needs to be uncompressed for each of these
  • Larger pages means slower index lookup as you need to scan half the page in average to find the key value

So how you control which indexes are packed and which are not ? Unfortunately at this point you can’t set compression on per index basics. Neither you can set index block size for the keys. So you can’t look at your index and say “OK. This is going to be typically scanned forward, so I can pack it” The only settings available is PACK_KEYS=0|1|DEFAULT. Value 0 disables compression for all keys. Value 1 forces it for all keys. Value DEFAULT will use key compression for character column type but not for numerical and other column types.

Also according to my tests it looks there is something special in how integer primary key is handled. I can’t see the index size difference between DEFAULT and 1 values for such key. However it I change it to “key” the size reduces if PACK_KEYS=1. Might be it is some kind of special hack 
The fact MyISAM will by default compress string keys but not integer keys is the biggest reason joins using string keys is so much slower compared to integer keys. Integer keys still best but for Innodb for example difference is not so large.

Let us try couple of benchmarks now. I’ve created simple table with 100.000 rows with columns. And I set id=c to keep it simple:

CREATE TABLE `t1` (
`id` int(10) unsigned NOT NULL ,
`c` varchar(20) NOT NULL default ”,
KEY `c` (`c`),
KEY `id` (`id`)
) ENGINE=MyISAM

Index size:

  • PACK_KEYS=DEFAULT – 1550K
  • PACK_KEYS=1 – 1453K
  • PACK_KEYS=0 – 8176K

As we can see difference between 1 and DEFAULT is rather small for this case, as integers are relatively short.

Now lets do some benchmarks. I’m testing 4 types of queries:

  1. select count(*) from t1, t1 t2 where t1.c=t2.c - simple join by string column
  2. select count(*) from t1, t1 t2 where t1.id=t2.id - same but using id column
  3. select c from t1 where c like “%abc%” order by c limit 1 - forward index scan
  4. select c from t1 where c like “%abc%” order by c desc limit 1 – reverse index scan
  • PACK_KEYS=DEFAULT Q1: 3.50s Q2: 0.35s Q3: 0.12s Q4: 1.26s
  • PACK_KEYS=0 Q1: 1.25s Q2:0.40s Q3: 0.14s Q4: 0.16s
  • PACK_KEYS=1 Q1: 3.50s Q2:1.55s Q3: 0.12s Q4: 1.26s

So we can see theory goes pretty much in hand with practice here. With DEFAULT configuration lookups for integer keys are fast and forward scans are. It is however slow to do reverse scan on the string index.

It is interesting to see PACK_KEYS=0 does not always improve performance even if data fits in memory. Take a look at Q3 for. The the reason perhaps is – smaller index side, which means less traffic to memory. With modern CPUs it might be actually faster to do a bit of uncompression than to traverse large memory areas. Reverse index scan performance got some 8 times faster and join on string value is almost 3 times faster.
With PACK_KEYS=1 we got join by integer key performing almost 5 times slower than it was – this is something really to watch out for.

Note – these numbers are for CPU bound workload. If your load is disk bound there are more reasons to have keys packed so cache hit is better. Especially if you can get hot indexes in memory by packing them it is almost no brainer

Summary:

    • Key prefix compression is cool feature and may give great space savings.
    • Defaults for MyISAM are good for most cases
    • Avoid joining on strings, it is much slower anyway
    • Watch for reverse index scans (see Handler_read_prev) these are much slower for packed keys
    • Be careful with PACK_KEYS=1 as it can slow down your integer joins a lot
    • Be careful with PACK_KEYS=0 as it can blow up your index size 10x times.

参考:

http://www.mysqlperformanceblog.com/2006/05/13/to-pack-or-not-to-pack-myisam-key-compression/

To pack or not to pack – MyISAM Key compression的更多相关文章

  1. #pragma pack(push) 和#pragma pack(pop) 以及#pragma pack()

    我们知道结构体内存对齐字节可以通过#pragma pack(n) 的方式来指定. 但是,有没有想过一个问题,某些时候我想4字节对齐,有些时候我又想1字节或者8字节对齐,那么怎么解决这个问题呢? 此时, ...

  2. (转)MyISAM Key Cache详解及优化

    原文:http://huanghualiang.blog.51cto.com/6782683/1372721 一.MyISAM Key Cache详解: 为了最小化磁盘I/O,MyISAM将最频繁访问 ...

  3. MyISAM Key Buffer 读/写/利用率(%) MylSAM平均每秒Key Buffer利用率(%) MylSAM平均每秒Key Buffer读命中率(%) MylSAM平均每秒Key Buffer写命中率(%)

    MyISAM Key Buffer 读/写/利用率(%) MylSAM平均每秒Key Buffer利用率(%)MylSAM平均每秒Key Buffer读命中率(%)MylSAM平均每秒Key Buff ...

  4. 详解C/C++中的的:#pragma pack(push) 、#pragma pack(pop) 和#pragma pack()

    前言 我们知道结构体内存对齐字节可以通过#pragma pack(n) 的方式来指定. 但是,有没有想过一个问题,某些时候我想4字节对齐,有些时候我又想1字节或者8字节对齐,那么怎么解决这个问题呢? ...

  5. PHP: 深入pack/unpack

    https://my.oschina.net/goal/blog/195749 PHP作为一门为web而生的服务器端开发语言,被越来越多的公司所采用.其中不乏大公司,如腾迅.盛大.淘米.新浪等.在对性 ...

  6. Python学习——struct模块的pack、unpack示例

    he struct module includes functions for converting between strings of bytes and native Python data t ...

  7. PHP: 深入pack/unpack 字节序

    http://my.oschina.net/goal/blog/195749?p=1 目录[-] 写在前面的话 什么是字节序 MSB和LSB 大端序 小端序 网络字节序 主机字节序 总结 pack/u ...

  8. php pack、unpack、ord 函数使用方法

    string pack ( string $format [, mixed $args [, mixed $... ]] ) Pack given arguments into a binary st ...

  9. [转]PHP: 深入pack/unpack

    From : http://my.oschina.net/goal/blog/195749 http://www.w3school.com.cn/php/func_misc_pack.asp PHP作 ...

随机推荐

  1. 小组ITalk网站开发中使用到的一些技巧

    ----->Display属性和Visibility属性:一个清除内容和框体,另一个只清除内容而保留窗体: $('#abc').css({ 'font-size' : '12px', '-web ...

  2. (C#)代理模式

    1.代理模式 为其他对象提供代理以控制对这个对象的访问. 远程代理:为一个对象在不同的地址空间提供举报代表.这样可以隐藏一个对象在不同地址空间的事实. 虚拟代理:是依据需要创建开销很大的对象.通过它来 ...

  3. 167. Add Two Numbers【LintCode by java】

    Description You have two numbers represented by a linked list, where each node contains a single dig ...

  4. 【转载】appium 操作汇总

    '''.appium api第二弹 锋利的python,这是初稿,2015/1/5 如有错误的地方,请同学们进行留言,我会及时予以修改,尽量整合一份ok的api 作者:Mads Spiral QQ:7 ...

  5. VT-x VT-d 虚拟化在win10中的问题

    win10真的是非常非常非常非常非常非常非常非常非常非常坑坑坑坑坑坑坑坑坑坑坑坑坑坑坑坑!!!!!! 自带虚拟Buff不说,我不用竟然会有冲突!!!! 一度让我怀疑,我的CPU VT-x坏掉了!!! ...

  6. 展示github中的页面(Github Pages)

    一.创建一个仓库,名为"user_name.github.io"(此处user_name替换为你自己的github用户名),并在根目录下创建index.html,则该仓库下的所有h ...

  7. epoll&ext4文件系统

    1.第一个终端运行nesttest,nesttest首先fork一个子进程,然后父进程退出,子进程首先打开一个txt普通文件对应fd为3,然后创建一个epfd,对应fd为4 lybxin@Inspir ...

  8. ubuntu软件管理apt与dpkg

    目前ubuntu系统主要有dpkg和apt两种软件管理方式两种区别如下 1.dpkg是用来安装.deb文件,但不会解决模块的依赖关系,且不会关心ubuntu的软件仓库内的软件,可以用于安装本地的deb ...

  9. C#创建Window服务图解,安装、配置、以及C#操作Windows服务

    一.首先打开VS2013,创建Windows服务项目 二.创建完成后对"Service1.cs"重命名位"ServiceDemo":然后切换到代码视图,写个服务 ...

  10. C++ 普通函数和虚函数调用的区别

    引出:写个类A,声明类A指针指向NULL,调用类A的方法会有什么后果,编译通过吗,运行会通过吗? #include<stdio.h> #include<iostream> us ...