最近一直在做管理系统,为了实现各种各样的数据处理,在MySQL开发方面积累了一些经验,以下几条都是在项目中沉淀下来的:
1、MySQL表中一行的长度不能超过65535字节,VARCHAR(N)使用额外的1到2字节来存储值的长度,如果N<=255,则使用 一个字节,否则使用两个字节;如果表格的编码为UTF8(一个字符占3个字节),那么VARCHAR(255)占用的字节数为255 * 3 + 2 = 767,这样,一行就最多只能有65535 / 765 = 85个VARCHAR(255)类型的列
2、MySQL有4种事务隔离级别
READ UNCOMMITTED: 可读取其他事务未提交的数据
READ COMMITTED: 只能读取已提交的数据,但是不可重复读
REPEATABLE READ: 可重复读
SERIALIZABLE: 事务串行化,必须等待当前事务执行完,其他事务才可以执行写操作,有多个事务同时设置SERIALIZABLE时会产生死锁
ERROR 1213 (40001): Deadlock found when trying to get lock; try restarting transaction
可以手工设置事务隔离级别:
SELECT @@global.tx_isolation;
SELECT @@session.tx_isolation;
SELECT @@tx_isolation; 等价于SELECT @@session.tx_isolation;
START TRANSACTION
SET [SESSION | GLOBAL] TRANSACTION ISOLATION LEVEL {READ UNCOMMITTED | READ COMMITTED | REPEATABLE READ | SERIALIZABLE}
COMMIT
ROLLBACK
3、MySQL的行锁
如果是InnoDB引擎,就可以在事务里使用行锁,格式为:
SELECT 列 FROM 表 [FORCE INDEX(PRIMARY)] WHERE 条件 FOR UPDATE
被加锁的行,其他事务也能读取但如果想写的话就必须等待锁的释放
只有查询用到的是主键索引或满足最左前缀的主键索引的一部分,并且具有明确的值
如:索引列=值、索引列=值1 or 索引列=值2、索引列 IN(值1,值2)才能实现行锁定,否则就会锁表
注:非主键索引会锁表,如果有多个索引可指定用主键索引(FORCE INDEX(PRIMARY)),以免锁表
4、存在相同主键的记录就更新记录,否则就插入新纪录
【1】REPLACE INTO,先删除再插入
【2】INSERT INTO ... ON DUPLICATE KEY UPDATE col=VALUES(col)
VALUES用来取插入的值,存在主键冲突时就更新,没有删除操作
5、分组统计数据,并将统计结果作为结果集的一列
【1】使用GROUP BY ,分组的统计结果是一行一行的
【2】使用IFNULL(SUM(IF(列=值,1,0)),0) ,分组的统计结果是一列一列的
6、使用GROUP BY分组统计时,如果要将字符串拼接起来,可使用GROUP_CONCAT,GROUP_CONCAT函数可以将多列与特定字符串拼起来作为一组,组与组之间再用指定字符串分割:
GROUP_CONCAT([DISTINCT] 列1[,字符串1,列2] [ORDER BY 列 DESC] SEPARATOR ',')
GROUP_CONCAT默认的最大长度限制为1024,可以修改这个最大限制值:
SELECT @@[SESSION | GLOBAL].group_concat_max_len
【1】my.cnf group_concat_max_len = 102400
【2】SET [SESSION | GLOBAL] group_concat_max_len = 102400
7、ON与WHERE的区别
执行连接操作时, 可先用ON先进行过滤,减少连接操作的中间结果,然后用WHERE对连接产生的结果再一次过滤。但是,如果是左/右连接,在ON 条件里对主表的过滤是无效的,仍然会用到主表的所有记录,连接产生的记录如果不满足主表的过滤条件那么从表部分的数据会置为NULL。
8、可用FIND_IN_SET从字符串(各项之间以逗号隔开)中查找是否包含某项,如果没找到就会返回0
判断2个集合是否有交集时,可将集合转化成字符串,元素之间以"|"隔开,然后用正则表达式来匹配,如:SELECT '20140501|20140618|20140619' REGEXP '20140504|20140619',有交集就返回1,无交集就返回0
9、可在多列上建立复合索引,使用复合索引时必须满足最左前缀。索引列的数据类型越小越好,这样可以将更多的索引数据放入内存,索引列应避免使用NULL值(加上NOT NULL限制)。
可用EXPLAIN EXTENDED 、SHOW WARNINGS查看重写后的SQL语句,可在慢查询日志中找出执行慢的SQL语句。要使用MySQL缓存,SQL语句必须严格一致(包括大小写),如果表的结构或数据发生变化,用到了这个表的SQL语句的缓存结果就会失效。如果SQL语句用到了多个索引,类似的SQL语句(只有参数值不同)可能会选用不同的索引。