一、字段类型和编码
1.1、mysql返回字符串长度:
CHARACTER_LENGTH方法(CHAR_LENGTH一样的)返回的是字符数,LENGTH函数返回的是字节数,一个汉字三个字节
1.2、索引长度:
varvhar等字段建立索引长度计算语句:**select count(distinct left(test,5))/count(*) from table; 越趋近1越好
1.3、字符集设置
mysql的utf8最大是3个字节不支持emoji表情符号,必须只用utf8mb4。需要在mysql配置文件中配置客户端字符集为utf8mb4。jdbc的连接串不支持配置characterEncoding=utf8mb4,最好的办法是在连接池中指定初始化sql,例如:hikari连接池,其他连接池类似spring.datasource.hikari.connection-init-sql=set names utf8mb4。否则需要每次执行sql前都先执行set names utf8mb4。
1.4、msyql排序规则(一般使用_bin和_genera_ci)
- utf8_genera_ci不区分大小写,ci为case insensitive的缩写,即大小写不敏感,
- utf8_general_cs区分大小写,cs为case sensitive的缩写,即大小写敏感,但是目前MySQL版本中已经不支持类似于***_genera_cs的排序规则,直接使用utf8_bin替代。
- utf8_bin将字符串中的每一个字符用二进制数据存储,区分大小写。
那么,同样是区分大小写,utf8_general_cs和utf8_bin有什么区别?
cs为case sensitive的缩写,即大小写敏感;bin的意思是二进制,也就是二进制编码比较。
utf8_general_cs排序规则下,即便是区分了大小写,但是某些西欧的字符和拉丁字符是不区分的,比如ä=a,但是有时并不需要ä=a,所以才有utf8_bin
utf8_bin的特点在于使用字符的二进制的编码进行运算,任何不同的二进制编码都是不同的,因此在utf8_bin排序规则下:ä<>a
1.5 列类型选择原则
-
列选择原则:
1:字段类型优先级 整型 > date,time > char,varchar > blob
2: 够用就行,不要慷慨 (如smallint,varchar(N))
3: 尽量避免用NULL()
-
关于null的测试
以10万行左右的表做试验,(可以用企业库里的dict表),顺序如下:
建dictnn表, 不允许为null;建dictyn表, 允许为nullalter table 表名 disable keys; #禁用2表的key insert into dictnn select id,if(id%2,word,'') from dict; insert into dictyn select id,if(id%2,word,null) from dict; alter table 表名 enable keys; #启用2表的key 观察磁盘文件大小 :)
-
text/blob使用磁盘临时表的测试
text,blob列, 选择这些列时,将不能使用内存临时表, 必须要把临时表写到磁盘上,速度慢 1:enum列在内部是用整型存储的. 2:enum存取有一个转换过程 3:思考enum/varchar的相比的优势 实验:用1万条左右的数据做实验 主键的选择: 主键用来区分,查找,和关联数据,非常重要. 1.在myisam中,字符串索引会被压缩,用字符串做主键性能不如整型 2. 用递增的值,不要用离散的值,离散值会导致文件在磁盘的位置有间隔,浪费空间且不易连续读取 3. UUID,也是逐步增长的,可以去掉"-",转换为整数 反范式的目的--减少表的关联查询 常用办法: 冗余字段和冗余表 冗余字段: 表中某字段存储另一表的统计信息 如discuz中threads表 (打开该表) 冗余表: 表中统计或汇总其他表的信息,又称汇总表 如discuz中的pre_common_onlinetime(打开该表) 本质-- 1:空间换时间 2:大任务分成小任务,分散执行 SET [GLOBAL | SESSION] TRANSACTION ISOLATION LEVEL { READ UNCOMMITTED | READ COMMITTED | REPEATABLE READ | SERIALIZABLE }