这个是对Java开发人员的MySQL使用手册.乱序持续更新中,建议不要使用5.6以下的版本,至少5.7以上.
@Temporal(TemporalType.TIMESTAMP)
@Column(name = "trade_time")
// "交易时间")
private Date tradeTime;
MySQL数据类型尽量不要使用枚举类型。如果需要增加新的枚举类型,需要全表更新,对于大数据量的更新场景,会造成锁表
定长的字符串,可以选择 CHAR。举个例子,身份证是定长类型,那么选择 CHAR 是非常合适的。
变长的字符串,可以选择 VARCHAR, 因为 VARCHAR 更加节省空间。
存储大文本的场景,可以考虑使用 BLOB 和 TEXT。
整数类型可以选择 UNSIGNED 属性,表示不允许负数,这样可以使得正数的上限提高一倍。
尽量避免使用 != 或 not in或 <> 等否定操作符。(在mysql8.0.19中not in 不会使索引失效)
尽量避免使用 or 来连接条件。
查询中的某个列有范围查询,则其右边所有列都无法使用索引优化查找。
复合索引中只要有一列含有 NULL值,那么这一列对于此复合索引就是无效的。(mysql8.0.19也能使用索引)
不要在列上使用函数和进行运算.
对于同时存在 WHERE 和 ORDER BY 的 SQL 语句,可以建立一个复合索引进行性能优化.
前缀索引就是将字段前缀的一部分作为索引。前缀索引有利于节省空间,也有利于提高查询速度,但是也有弊,1.不能使用覆盖索引了2.增加查询次数(前缀索引的目的是先初步筛选出id,然后再查询完整数据再对比是否满足条件)。3.不支持范围查询。前缀索引的使用方式:alter table SUser add index index2(email(6));
倒序存储就是将字段内容倒序存入数据库。字段内容区分度不够时使用倒序存储能增加查询效率。缺点是只支持常规等值查询
hash字段索引就是创建一个hash字段,存储索引字段内容的hash值。缺点是不能使用范围查询。使用时查询方式为:select field_list from t where id_card_crc=crc32('input_id_card_string') and id_card='input_id_card_string'
如下是本人在最新MySQL8.0.19版本中测试结果:
DROP TABLE IF EXISTS `Student`;
CREATE TABLE `Student` (
`id` int(0) UNSIGNED NOT NULL AUTO_INCREMENT,
`name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_bin NULL DEFAULT NULL,
`age` int(0) UNSIGNED NULL DEFAULT NULL,
`memo` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_bin NULL DEFAULT NULL,
`classes` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_bin NULL DEFAULT NULL,
`school` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_bin NULL DEFAULT NULL,
PRIMARY KEY (`id`) USING BTREE,
INDEX `name_index`(`name`) USING BTREE,
INDEX `age_index`(`age`) USING BTREE,
INDEX `class_school_index`(`classes`, `school`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_bin ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of Student
-- ----------------------------
INSERT INTO `Student` VALUES (1, 'johnny', 29, 'test', 'nanshan', 'NanShanSCHOOL1');
INSERT INTO `Student` VALUES (2, 'HUANG', 34, 'HUANGTEST', '', 'NanShanSCHOOL2');
INSERT INTO `Student` VALUES (3, 'Johnny', 23, 'test', 'nanshan', 'NanShanSCHOOL3');
INSERT INTO `Student` VALUES (4, 'Johnny1', 21, 'sdf ', NULL, 'NanShanSCHOOL3');
表有4个索引,其中一个是主键索引,一个是复合索引.
PRIMARY KEY (`id`) USING BTREE,
INDEX `name_index`(`name`) USING BTREE,
INDEX `age_index`(`age`) USING BTREE,
INDEX `class_school_index`(`classes`, `school`) USING BTREE
EXPLAIN SELECT * FROM Student WHERE NAME LIKE 'Johnny%'; -- 走索引
EXPLAIN SELECT * FROM Student WHERE NAME LIKE '%Johnny%'; -- 不走索引
EXPLAIN SELECT * FROM Student WHERE LEFT(NAME,2) = 'Jo'; -- 对列使用了函数不走索引
EXPLAIN SELECT * FROM Student WHERE NAME = 1; -- 字符串与数字比较,不走索引
EXPLAIN SELECT * FROM Student WHERE NAME = '1'; -- 走索引
EXPLAIN SELECT * FROM Student WHERE age +1> 23; -- 不走索引,每一行都参与运算
EXPLAIN SELECT * FROM Student WHERE age < 20 or age >60 ; -- 走索引
EXPLAIN SELECT * FROM Student WHERE id = 3; -- 走索引
EXPLAIN SELECT * FROM Student WHERE school = 'NanShanSCHOOL3' and classes = 'nanshan'; -- 走索引
EXPLAIN SELECT * FROM Student WHERE classes = 'nanshan' and school = 'NanShanSCHOOL3' ; -- 走索引 有个列classes有默认的null值也走了索引
EXPLAIN SELECT * FROM Student WHERE classes != 'nanshan';
EXPLAIN SELECT * FROM Student WHERE age < 60 and age >20 ; -- 走索引
EXPLAIN SELECT * FROM Student WHERE age between 20 and 50 ; -- between走索引
EXPLAIN SELECT * FROM Student WHERE age not between 20 and 50 ; -- not between走索引
EXPLAIN SELECT * FROM Student WHERE age in(20, 23) ; -- in走索引
EXPLAIN SELECT * FROM Student WHERE age not in(20, 23) ; -- not in走索引
-- 查询当前数据库版本
select version();