MySQL的存储引擎API工作时需要在服务器层和存储引擎层之间通过行缓冲格式拷贝数据,然后在服务器层将缓冲内容解码成各个列。
从行缓冲中将编码过的列转换成行数据结构的操作代价非常高
MyISAM的变长行结构和InnoDB的行结构总是需要转换,转换的代价依赖于列的数量。
MySQL限制了每个关联操作最多只能有61张表,单个查询最好在12个表以内做关联
当确实需要表示未知值时不要害怕使用NULL
范式化的数据库中,每个事实数据会出现并且只出现一次。
反范式化的数据库中,信息是冗余的,可能会存储在多个地方
缺点是通常需要关联
避免关联
即使表没有使用索引,当数据比内存大时可能比关联要快得多
单独的表能使用更有效的索引策略
最常见的反范式化数据的方法是复制或者缓存,在不同的表中存储相同的特定列
有时提升性能最好的方法是在同一张表中保存衍生的冗余数据
有时候需要创建一张完全独立的汇总表或缓存表
“缓存表”表示存储那些可以比较简单地从schema其他表获取数据的表,但是这些数据每次获取的速度都比较慢
“汇总表”保存的是使用GROUP BY语句聚合数据的表
汇总表举例:
以网站为例,获取之前24小时内发送的消息数,可以每小时生成一张汇总表,把前23个完整的小时的统计表中的计数全部加起来,最后加上开始和结束阶段内不完整的小时内的计数
计算最活跃的用户或者最常见的“标签”是这种操作的典型例子
缓存表举例:
需要很多不同的索引组合来加速各种类型的查询。这些矛盾的需求就需要创建一张只包含主表中部分列的缓存表。
一个有用的技巧是对缓存表使用不同的存储引擎。
例如,主表使用InnoDB,缓存表用MyISAM将会得到更小的索引占用空间,并且可以做全文搜索。有时甚至想把整个表导出MySQL,插入到专门的搜索系统中获得更高的搜索效率
使用缓存表和汇总表时,必须决定是实时维护数据还是定期重建
定期重建不只是节省资源,也可以保持表不会有很多碎片,以及有顺序组织的索引
重建汇总表和缓存表时,通常需要保证数据在操作时仍然可用,此时需要建立“影子表”,完成了建表操作后可以通过一个原子的重命名操作切换影子表和原表,例如:
物化视图实际上是预先计算并且存储在磁盘上的表,可以通过各种各样的策略刷新和更新
MySQL并不原生支持物化视图,但是可以使用开源工具Flexviews,Flexviews通过提取对源表的修改,可以重新计算物化视图的内容。
Flexviews不仅可以获得每行的新值,还可以不需要查找源表就能知道每行数据的旧版本
可以用这种表缓存一个用户的朋友数,文件下载次数等。创建一个独立的计数器表小且快,可以帮助避免查询缓存失效
MySQL执行大部分修改表结构操作的方法是用新的结构创建一个空表,从旧表中查出所有数据导入新表,然后删除旧表。
大部分ALTER TABLE将导致MySQl服务中断
技巧一:
现在不提供服务的机器上执行ALTER TABLE操作,然后和提供服务的主库进行切换
技巧二:
影子拷贝:用要求的表结构创建一张和源表无关的新表,然后通过重命名和删表操作交换两张表,也有一些工具可以帮助进行影子拷贝工作
下面这些操作是有可能不需要重建表的
基本的技术是为想要的表创建一个新的.frm文件,然后用它替换掉以及存在的那张表的.frm文件:
1.创建一张有相同结构的空表,并进行所需要的修改
2.执行FLUSH TABLES WITH READ LOCK。这将会关闭所有正在使用的表,并且禁止任何表被打开
3.交换.frm文件
4.执行UNLOCK TABLES
为了高效地载入数据到MyISAM表中,有一个常用的技巧是先禁用索引、载入数据,然后重新启用索引
这个技巧能发挥作用,是因为构建索引的工作被延迟到数据完全载入以后,这个时候已经可以通过排序来构建索引了
这个办法对唯一索引无效,因为DISABLE KEYS只对非唯一索引有效
现代版本的InnoDB版本中,有一个类似的技巧,先删除所有的非唯一索引,然后增加新的列,最后重新创建删除掉的索引
也可以使用骇客方法