Java开发者MySQL使用手册(持续更新)

这个是对Java开发人员的MySQL使用手册.乱序持续更新中,建议不要使用5.6以下的版本,至少5.7以上.

  1. MySQL的数据类型。MySQL支持多种类型,大致可以分为三类:数值、日期/时间和字符串(字符)类型。这个一定要熟悉,因为关系到你设计的表是否合理.可以参考MySQL 数据类型.
  2. 字符集不要设置为utf8 ,改为utf8mb4.COLLATE使用utf8mb4_general_ci
  3. 金额字段使用 int 或者 bigint 类型。如果需要存储到分的维度,需要 *100 进行放大.或者使用 decimal 类型,避免精度丢失。如果使用 Java 语言时,需要使用 BigDecimal 进行对应. FLOAT 和 DOUBLE 都是不精确的,如果要实现精确浮点运算,不能选择FLOAT 和 DOUBLE。
  4. 如果主键索引是业务索引字段,并且长度达到十几,比如身份证号,建议使用自增主键索引,然后给你的业务字段创建普通索引
  5. 查询所有有自增字段的表select * from information_schema.`COLUMNS` where EXTRA='auto_increment' and TABLE_SCHEMA='payment'
  6. like 的方式进行查询,在 like “value%” 可以使用索引,但是对于 like “%value%” 这样的方式,执行全表查询。
  7. 使用了复合索引时,遵守“最左前缀”原则,即在查询条件中使用了复合索引的第一个字段,索引才会被使用。因此,在复合索引中索引列的顺序至关重要。
  8. DATETIME 和 TIMESTAMP 都可以存储相同类型的数据,而 TIMESTAMP 只使用 DATETIME 一半的存储空间。通常情况下,建议优先考虑 TIMESTAMP,因为它的空间利用率更高。用法@Temporal(TemporalType.TIMESTAMP)
  9. @Temporal(TemporalType.TIMESTAMP)
    @Column(name = "trade_time")
    // "交易时间")
    private Date tradeTime;
  10. MySQL数据类型尽量不要使用枚举类型。如果需要增加新的枚举类型,需要全表更新,对于大数据量的更新场景,会造成锁表

  11. 定长的字符串,可以选择 CHAR。举个例子,身份证是定长类型,那么选择 CHAR 是非常合适的。

  12. 变长的字符串,可以选择 VARCHAR, 因为 VARCHAR 更加节省空间。

  13. 存储大文本的场景,可以考虑使用 BLOB 和 TEXT。

  14. 整数类型可以选择 UNSIGNED 属性,表示不允许负数,这样可以使得正数的上限提高一倍。

  15. 尽量避免使用 !=not in<> 等否定操作符。(在mysql8.0.19中not in 不会使索引失效)

  16. 尽量避免使用 or 来连接条件。

  17. 查询中的某个列有范围查询,则其右边所有列都无法使用索引优化查找。

  18. 复合索引中只要有一列含有 NULL值,那么这一列对于此复合索引就是无效的。(mysql8.0.19也能使用索引)

  19. 不要在列上使用函数和进行运算.

  20. 对于同时存在 WHERE 和 ORDER BY 的 SQL 语句,可以建立一个复合索引进行性能优化.

  21. 前缀索引就是将字段前缀的一部分作为索引。前缀索引有利于节省空间,也有利于提高查询速度,但是也有弊,1.不能使用覆盖索引了2.增加查询次数(前缀索引的目的是先初步筛选出id,然后再查询完整数据再对比是否满足条件)。3.不支持范围查询。前缀索引的使用方式:alter table SUser add index index2(email(6));

  22. 倒序存储就是将字段内容倒序存入数据库。字段内容区分度不够时使用倒序存储能增加查询效率。缺点是只支持常规等值查询

  23. 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();

 

你可能感兴趣的:(MySQL)