MySQL触发器的适用场景和约束

最适合的场景可能是:冗余设计中的数据联动,以及summary table这种。 这两类逻辑用触发器来搞定会比用上层代码搞定要简洁的多。 性能方面没有问题,在InnoDB中,它还可以保证原子性。 不过, 1. 这类逻辑比较隐蔽,容易被忽略,埋坑。 2. 调试难,如果没有全局梳理,一不小心可能导致死锁。 3. 一旦要分表分库,可能处理起来会比在上层应用中处理更棘手。

MySQL query cache出现负面作用的情形

1. 写语句特别频繁的场景不适合使用query cache,  因为query cache会被不停地失效,导致cache miss, 使用query cache纯粹是浪费性能。因为query cache本身也有使用代价,执行语句前它要先查一下cache中有没有,如果没有,从表中查到值之后还要更新一下cache 2. query cache累积过多可能出问题。当表中数据修改时,所有相关的cache都要失效;在失效过程中,要访问cache的查询都会被阻塞(即使跟这张表没关系);如果cache很多,最终给人的感觉是数据库长时间对查询无响应。 3. innodb中的长事务可能会使query cache失效。只要事务中修改了这张表,yi 会导致这个表关联的query cache在事务结束前全局失效:不仅本事务中会cache miss, 其他事务中也会cache miss.

MySQL query cache怎么个缓存法

1. query cache的key是sql字符串,并且要求精确匹配:大小写不一样或者多了一个空格,都会导致cache miss 2. query cache直接把用户输入的原始sql作为key, 不是把解析后或优化后的sql作为key,也不会把其中的子查询独立缓存 2. 存储过程中的sql结果不会被缓存 3. 如果一个sql会产生不确定的结果(即使表中数据没有变化也会不确定),比如select now(), MySQL就不会缓存它的结果 4. 只要表中数据有任何变化,就会导致本表相关的所有query cache统统失效

MySQL使用limit条件时要注意offset不能太大

MySQL使用limit条件时要注意offset不能太大。 这样还可以: select * from user order by user_name limit 100, 20 这样就不好了: select * from user order by user_name limit 10000, 20 这条语句实际上是把 1-10020行都取出来,然后再丢掉前10000条记录,最后再返回剩下的20条记录。所以代价会非常高。 如果数据库是innodb且user_name上有索引的话,可以把sql改写成这样来优化一下: select * from user join (select id from user order by user_name limit 10000,20) as lim on user.id = lim.id 这里仍然会扫描1万多次,但扫描的不是data rows, 而是user_name上的index(并且是covering index) ; 扫完索引之后,再根据扫出的id把20行数据取出来。也就是说,磁盘读会小很多,速度也会快很多。

注意:limit条件不会影响MySQL Explain Plan中的rows结果

limit条件不会影响MySQL Explain Plan中的rows结果。比如, explain select * from t limit 10 输出的rows值可能是1百万(如果t中有1百万数据)。 但实际上,MySQL不会为这十行数据扫描整张表的。 Peter Zaitsev说: LIMIT is not taken into account while estimating number of rows Even if you have LIMIT which restricts how many rows will be examined MySQL will still print full number 如果不知道这个潜规则,会被explain plan迷惑死。这是典型的MySQL制造者的懒惰给使用者造成的麻烦。

MySQL: count()的坑

count(*), count(1), count(someColumn) 倒底有没有分别? 使用count(someColumn)只取一列,会不会性能好点? 如果是这样的话,那count(1)是不是性能最佳? 答案: 1. count(*)和count(1)完全是一码事:都是用来数“行数”的。MySQL遇到"*", 并不会去展开它。在性能方面,这类查询会走covering index.  2. count(someColumn)跟其他完全不同,它数的是someColumn列中非NULL值的个数。在性能方面,系统会根据someColumn有没有索引,来决定走不走covering index. 例: drop table if exists play_count; create table play_count( id bigint auto_increment not null, indexed_column varchar(50), –有索引列 non_indexed_column varchar(50), –无索引列 primary key(id), key idx(indexed_column) ); –插入三行数据,存在空值 insert into play_count(indexed_column,non_indexed_column) value(‘a’,null); insert into play_count(indexed_column,non_indexed_column) value(null,’b’); insert into play_count(indexed_column,non_indexed_column) value(‘c’,’c’); –count查询 select count(*) …

MySQL: count()的坑 Read More »

高并发应用中的MySQL:尽量不要表连接

对于高并发应用中的MySQL,按照我的经验,尽量不要表连接;MySQL Optimizer在处理表连接时有时很不智能,搞出个大坑。比如这个。 在需要表连接的场景,尽量把它拆解掉,这就叫做 Join Decomposition. 个人常用的办法有两个: 1.冗余 2.分成两步执行: 先查出符合条件的A表的ID,再根据这些ID使用IN字句去B表中查询。 消除表连接还有个附加好处是两个表不一定要放在同一个库里,这样你做垂直分库会比较自由。

MySQL: Explain Plan中的Using Where意思是扫描数据后扔掉了一部分

Using Where意思是 扫描(examine)数据后扔掉了一部分,只返回剩下的。常见的例子是根据无索引的字段进行搜索。 select * from user where description = ‘to be a better man’ 这时MySQL必须把所有数据找出来,然后“使用Where条件”判断一下description是不是"to be a better man"; 等找到之后再把不符合条件的扔掉。