查询缓存
保存了SELECT语句的完整结果集。1.检查缓存命中
缓存是一个查找表,查找键是查询文本,当前数据库,客户端协议的版本,以及其他影响实际查询结果的因素的哈希值
检查缓存的时候,不会对语句进行解析,正则化或参数化,精确使用查询语句
不会储存有不确定结果的查询。包含不确定函数
额外开销:读取查询前必须检查缓存
查询可以被缓存,在产生结果之后保存会带来额外开销
写入数据的查询有额外开销,必须使缓存中相关的数据表失效
InnoDB事务限制了查询缓存的失效。当事务内部语句更改了表,服务器会使所有引用了该表的查询缓存失效。长期运行的事务会增加查询缓存未命中的数量。
2.使用缓存
查询缓存完全存储在内存中。
本身需要消耗40KB内存,查询缓存的内存池被分为大小可变的块。每一块知道自己的类型,大小,数据量和指向前一个和后一个逻辑块和物理块的指针。内存块分为存储查询结果,查询使用的表的列表,查询文本等。
服务器启动时候会初始化查询缓存使用的内存。内存池最开始只有一个块。
分配内存块的速度较慢,服务器需要查看可用内存的列表并且找到大小合适的块。
检查是否从查询缓存中受益的简单办法就是检查缓存命中率,是缓存提供的查询结果的数量。Qcache_hits/(Qcache_hits + Com_select).
缓存未命中原因:查询不可缓存
查询的结果以前缓存过,后被服务器移出了
缓存失效
缓存失效可能因为碎片,内存不足或数据改变。检查Com_*(Com_update,Com_delete等)了解多少查询修改了缓存。检查Qcache_lowmem_prunes的值了解多少查询因内存不足而失效。
读写并重的表,不会从查询缓存中获益
如果服务器收到同一个查询语句之前,缓存失效了,保存结果就没有意义。可以检查Com_select和Qcache_inserts相对大小。如果差不多所有select语句都是缓存未命中,并把结果保存到缓存中,Qcache_inserts就会和Com_select差不多大小。
3.查询缓存的维护和调优
Query_cache_type 表示缓存是否被激活。选项有ON,OFF,DEMAND
Query_cache_size 分配给查询的总内存
Query_cache_min_res_unit 分配缓存块最小值
Query_cache_limit 限制MySQL存储的最大结果
Query_cache_wlock_invalidate 是否缓存其他联接已经锁定了的表。通常保持默认值OFF就可以了
减少碎片
没有办法避免所有碎片,仔细选择query_cache_min_res_unit可以避免造成大量的内存浪费。关键在于每一个新块和服务器已分配给存储结果的块找到平衡。
可以用使用的内存(query_cache_size-Query_free_memory)除以Qcache_queries_in_cache得到查询的平均大小。
检查Qcache_free_blocks来探测缓存中碎片的情况。如果Qcache_free_blocks大致等于Qcache_total_blocks/2,说明碎片很严重。如果Qcache_lowmem_prunes值正在增加,并且有大量的自由块,意味着碎片导致查询正被从缓存中永久删除。
FLUSH QUERY CACHE移除碎片。把所有存储块向上移动,把自由块移到底部。
提高查询缓存的可用性
1.缓存没有碎片,但命中率不高,给缓存分配较少内存
2.服务器找不到足够大小的块来存储结果,应该从缓存中清理掉一些查询
3.很多自由块,碎片很少,内存不足引起的清理工作很少,但命中率不高,说明不能从缓存中获益
MySQL中存储代码
MySQL可以使用触发器,存储过程和存储函数把代码保存到服务器内部1.存储过程比较快的原因是避免了网络通信,解析,优化等开销(增加服务器负荷)
2.触发器可以在执行insert,update,delete时候运行代码。不会返回结果,但是可以读取或修改数据。对于每个事件,在每个表上只有一个触发器,只支持行级触发器。对于约束,系统维护任务,以及在同步中保持非正则化数据比较有用
3.事件,在某个特定事件或时间间隔执行一次预先写好的SQL代码。常用用法将复杂SQL语句包装到一个存储过程中,然后调用一下。与连接无关,运行在一个独立定时器线程上,但需要激活。
4.游标,只能向前只读游标,只在存储过程中使用
5.准备语句,客户端向服务器发送一个实际查询的原型,然后对该原型进行解析和处理,将部分优化过的原型保存起来,给客户端返回一个状态句柄。客户端通过定义状态句柄重复执行查询。
准备语句比多次执行查询效率高:1.服务器只需解析一次查询
2.服务器缓存了一部分执行计划
3.通过二进制发送参数比通过ASII码要快
4.只发送参数
5.直接把参数保存在服务器的缓冲区内