mysql学习Day1 Limit、Like 、正则表达式、以及MySQL8.0新特性

文章目录

  • MySQL8.0 新特性
    • 1. 等值查询增强
    • 2. 隐藏索引
    • 3. 降序索引
    • 4. 函数索引
    • 5. 窗口函数
    • 6. InnoDB增强
      • 6.1 元数据增强
      • 6.2 原子DDL操作
      • 6.3. 自增序列增强
      • 6.4 Innodb_autoinc的变换
      • 6.5 死锁检测
      • 6.6 锁定行方式改变
      • 6.7 索引并行读取
      • 6.8 其它的改进
    • 2 - between A and B 在AB中间的值都行 ,in只能括号是其中的值
    • 3-空值查询 XXX IS NULL 或者 XXX IS NOT NULL
    • 4- NOT
    • 5-LIKE 注意三个的区别,下划线_ 只能匹配一个字符,%匹配多个
    • 6-正则表达式
    • 7-REGEXP 和LIKE 的区别在于like匹配的是整个字符串而REGEXP匹配的是子串,但是可以用^ $起到和like相同的作用,而同样LIKE也可以用 % %起到REGEXP的作用。
    • 8- 常使用的函数

MySQL8.0 新特性

1. 等值查询增强

mysql官网介绍新特性地址

https://blog.csdn.net/horses/article/details/85038949

等值查询博客介绍
等值查询官网介绍
其实博客中介绍的很详细,但是我这里也会说明几点:
我们为了介绍等值查询先创建3张表,而且往每张表里面插入100万条记录

CREATE TABLE t1 (c1 INT, c2 INT);
CREATE TABLE t2 (c1 INT, c2 INT);
CREATE TABLE t3 (c1 INT, c2 INT);

MySQL怎么快速插入100条记录呢?很简单,如下:

--往T1里面插入100万条,同理可以插入t2,t3
INSERT INTO t1
-- INSERT INTO t2
-- INSERT INTO t3
WITH RECURSIVE t AS (
  SELECT 1 AS c1, 1 AS c2
  UNION ALL
  SELECT t.c1 + 1, t.c1 * 2
    FROM t
   WHERE t.c1 < 1000000
)
SELECT *
  FROM t;

A:连接条件

  1. 等值查询适用于两张表关联查询,而且是等值条件,比如
SELECT * FROM  t1, t2 WHERE  t1.c1 = t2.c1;
SELECT * FROM t1 JOIN t2  ON t1.c1=t2.c1;
  1. 或者多个等值查询,或者多个等值连接中,每一个都至少有一个等值连接
## 1. 可以
EXPLAIN ANALYZE SELECT * FROM  t1, t2 ,t3 WHERE  t1.c1 = t2.c1 and t3.c1 =t2.c1;
## 2.可以
SELECT * FROM t1 JOIN t2  ON (t1.c1 = t2.c1 AND t1.c2 < t2.c2)
JOIN t3 ON (t2.c1 = t3.c1);

  1. 但是如果多个等值连接中,其中一个不满足等值查询就不能用hash join了,比如
EXPLAIN  FORMAT=TREE SELECT * FROM  t1, t2,t3  WHERE  t1.c1 = t2.c1 and t3.c1  > t2.c1;
##或者这样写都是不能用的
SELECT * FROM t1   JOIN t2   ON (t1.c1 = t2.c1)
 JOIN t3 ON (t2.c1 < t3.c1) 

B:笛卡尔积查询

因为连接如: select * from a,b where a.id =b.id 其实就是一种笛卡尔积的方式,而且即使没有where条件其实还是笛卡尔积的方式,如:select * from a,b 那么其实上面的等值连接也可以用到笛卡尔积方式的连接上,如:select * from a, b where a.id>10,实际上诉应用就是:
如下:两种都可以用到hash join

 EXPLAIN ANALYZE SELECT * from t1 ,t2 where t1.c1<50
 EXPLAIN ANALYZE SELECT * from t1 JOIN t2 where t1.c1<50

C:查看是否用了等值连接

  1. EXPLAIN FORMAT=TREE命令可以看到执行计划中的 hash join,例如:
EXPLAIN FORMAT=TREE 
SELECT * FROM  t1, t2 WHERE  t1.c1 = t2.c1;
--如下所示
mysql> EXPLAIN FORMAT=TREE SELECT * FROM  t1, t2 WHERE  t1.c1 = t2.c1;
+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| EXPLAIN                                                                                                                                                                                               |
+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| -> Inner hash join (t2.c1 = t1.c1)  (cost=199274951320.59 rows=199274851191)
    -> Table scan on t2  (cost=0.02 rows=1995918)
    -> Hash
        -> Table scan on t1  (cost=100539.40 rows=998412)
 |
+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.03 sec)
  1. EXPLAIN ANALYZE命令也可以显示 hash join 的使用信息。这也是该版本新增的一个功能。
EXPLAIN ANALYZE 
SELECT * FROM  t1, t2 WHERE  t1.c1 = t2.c1;

--如下:
mysql> EXPLAIN ANALYZE
    -> SELECT * FROM  t1, t2 WHERE  t1.c1 = t2.c1;
+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| EXPLAIN                                                                                                                                                                                                                                                                                                                                                            |
+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| -> Inner hash join (t2.c1 = t1.c1)  (cost=199274951320.59 rows=199274851191) (actual time=1866.313..3850.063 rows=2000000 loops=1)
    -> Table scan on t2  (cost=0.02 rows=1995918) (actual time=18.531..1259.661 rows=2000000 loops=1)
    -> Hash
        -> Table scan on t1  (cost=100539.40 rows=998412) (actual time=0.124..1331.061 rows=1000000 loops=1)
 |
+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (3.99 sec)

2. 隐藏索引

博客介绍

  1. MySQL 8.0 支持隐藏索引(invisible index),也称为不可见索引。隐藏索引不会被优化器使用。主键不能设置为隐藏(包括显式设置或隐式设置)。

  2. 索引默认是可见的(visible)。使用CREATE TABLE、CREATE INDEX 或ALTER TABLE语句的VISIBLE或者INVISIBLE选项设置一个新建索引的可见性:

ALTER TABLE t1 ALTER INDEX i_idx INVISIBLE;
ALTER TABLE t1 ALTER INDEX i_idx VISIBLE;
  1. 查询当前索引是否可见
SELECT INDEX_NAME, IS_VISIBLE
       FROM INFORMATION_SCHEMA.STATISTICS
       WHERE TABLE_SCHEMA = 'xxx'   AND TABLE_NAME = 'tableXXX';


show index from tableXXX
  1. 功能:软删除索引、灰度发布

不可见索引特性可以用于测试删除某个索引对于查询性能的影响,同时又不需要真正删除索引,也就避免了错误删除之后的索引重建。对于一个大表上的索引进行删除重建将会非常耗时,而将其设置为不可见或可见将会非常简单快捷。
5. 主键索引不能设置为不可见,如果没有显式的设置主键,但是 NOT NULL 字段 j 上存在一个唯一索引,它实现了和主键相同的数据约束,不能设置为不可见:

当创建表时没有显示定义主键时.
1 首先判断表中是否有非空的整形唯一索引,如果有,则该列为主键
(这时候可以使用  select _rowid from table ).查询到主键列
2 如果没有符合条件的则会自动创建一个6字节的主键(该主键是查不到的).

3. 降序索引

比如创建如下表

CREATE TABLE `t` (
  `c1` int(11) DEFAULT NULL,
  `c2` int(11) DEFAULT NULL,
  `id` int(11) NOT NULL,
  PRIMARY KEY (`id`),
  KEY `idx1` (`c1`,`c2`),
  KEY `idx2` (`c1`,`c2` DESC),
  KEY `idx3` (`c1` DESC,`c2`),
  KEY `idx4` (`c1` DESC,`c2` DESC)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;

-- ----------------------------
-- Records of t
-- ----------------------------
INSERT INTO `t` VALUES ('1', '1', '1');
INSERT INTO `t` VALUES ('2', '2', '2');
INSERT INTO `t` VALUES ('3', '3', '3');
INSERT INTO `t` VALUES ('4', '4', '4');

  1. 表的定义中包含了 4 个不同的索引。优化器可以为不同的ORDER BY子句使用正向索引扫描,而不需要执行 filesort 排序:
 explain select * from tORDER BY c1 ASC, c2 ASC    -- optimizer can use idx1
 explain select * from tORDER BY c1 DESC, c2 DESC  -- optimizer can use idx4
 explain select * from tORDER BY c1 ASC, c2 DESC   -- optimizer can use idx2
 explain select * from tORDER BY c1 DESC, c2 ASC   -- optimizer can use idx3

  1. 降序索引只支持 InnoDB 存储引擎,并且存在以下限制:
    降序索引支持 BTREE 索引,但不支持 HASH 索引。降序索引不支持 FULLTEXT 或者 SPATIAL 索引。
  2. 当然如果只有一个索引,而且order by不是指定的索引顺序,也能用到索引。如下:
CREATE TABLE `t_2` (
  `c1` int(11) DEFAULT NULL,
  `c2` int(11) DEFAULT NULL,
  `id` int(11) NOT NULL,
  PRIMARY KEY (`id`),
  KEY `idx1` (`c1` ASC ,`c2` DESC)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;

下面还是能支持索引的

explain select * from t_2 ORDER BY c1 ASC, c2 ASC

4. 函数索引

MySQL 8.0.13 以及更高版本支持函数索引(functional key parts),也就是将表达式的值作为索引的内容,而不是列值或列值前缀。 将函数作为索引键可以用于索引那些没有在表中直接存储的内容。
下面创建一个包含函数索引的表

CREATE TABLE `t1` (
  `id` int(11) NOT NULL,
  `col1` int(11) DEFAULT NULL,
  `col2` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `func_index` ((abs(`col1`))),
  KEY `idx1` (((`col1` + `col2`))),
  KEY `idx2` (((`col1` + `col2`)),((`col1` - `col2`)),`col1`),
  KEY `functional_index` (((`col1` * 40)) DESC)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;

-- ----------------------------
-- Records of t1
-- ----------------------------
INSERT INTO `t1` VALUES ('1', '1', '1');
INSERT INTO `t1` VALUES ('2', '2', '2');
INSERT INTO `t1` VALUES ('3', '3', '3');
  1. 多列索引可以同时包含非函数列和函数列。
  2. 函数索引支持ASC和DESC选项。
  3. SPATIAL 索引和 FULLTEXT 索引不支持函数索引。
  4. 只有where条件满足函数索引的时候才能命中索引,比如
## 能用索引functional_index
EXPLAIN SELECT * from t1 where col1*40 =1
## 不能用索引
EXPLAIN SELECT * from t1 where col1 =1
  1. 如果要删除一个在函数索引中使用的字段,必须先删除该索引;否则将会产生错误。
  2. 虽然非函数索引支持前缀索引,但是函数索引不支持使用字段的前缀。替代的方法就是使用 SUBSTRING() 函数(或者后文中的 CAST() 函数)。如果使用 SUBSTRING() 函数定义索引列,要想在查询中使用该索引,必须在WHERE 子句中使用同样的 SUBSTRING() 函数。以下示例中,只有第二个SELECT能够使用索引,因为它的查询中使用了和索引定义相同的 SUBSTRING() 函数和参数:
CREATE TABLE tbl (
id  int(11) PRIMARY key ,
  col1 LONGTEXT,
  INDEX idx1 ((SUBSTRING(col1, 1, 10)))
);
## 不能用索引
EXPLAIN SELECT * FROM tbl WHERE SUBSTRING(col1, 1, 9) = '123456789';
## 能用索引idx1 
EXPLAIN SELECT * FROM tbl WHERE SUBSTRING(col1, 1, 10) = '1234567890';

5. 窗口函数

6. InnoDB增强

6.1 元数据增强

  1. MySQL8.0删除之前版本的元数据文件,比如.frm .opt文件
  2. 将MySQL系统表和数据字典表全部改为InnoDB引擎
  3. 支持原生的DDL语句
  4. 简化Information_schema的实现,提高数据字典的访问性能
  5. 提供序列化字典信息SDI的支持,以及ibd2sdi工具

6.2 原子DDL操作

  1. drop table t1,t2 但是t2表不存在 5.7 版本和8.0版本处理的逻辑是不一样的,
    5.7是t1删除了而且报错,8.0是都没有删除,而且报错了

6.3. 自增序列增强

因为在5.7中自增列是写到了内存中而没有更新binlog,如果出现故障或者重启自增列是扫描当前表的最大值
这样如果是已经删除的id,就会重新出现,但是8.0不会
比如我们删除最大id是100的记录,重启5.7版本服务器,则下次插入的还是100,但是MySQL8.0则是101

6.4 Innodb_autoinc的变换

在MySQL8.0中值是2,锁是交叉生成的,主从复制是基于行进行复制的
1是连续模式,主从是基于语句复制的,
由1变成2,提高了并发,在MySQL主从复制中,提高了性能

mysql> show  variables like '%Innodb_autoinc%';
+--------------------------+-------+
| Variable_name            | Value |
+--------------------------+-------+
| innodb_autoinc_lock_mode | 2     |
+--------------------------+-------+
1 row in set

6.5 死锁检测

MySQL为了死锁检测增加了一个动态的变量 innodb_deadlock_detect

mysql>  show variables like 'innodb_deadlock_detect';
+------------------------+-------+
| Variable_name          | Value |
+------------------------+-------+
| innodb_deadlock_detect | ON    |
+------------------------+-------+
1 row in set

也可以关闭,但是建议不要关闭

set global innodb_deadlock_detect =off;
##死锁超时时间5秒
set global innodb_lock_wait_timeout=5;

6.6 锁定行方式改变

## 行锁,独占锁
select * from tableXX where id =1 for update ;
## 行锁,共享锁
select * from tableXX where id =1 for share ;


## 行锁,如果当前数据被锁定,则直接返回错误
select * from tableXX where id =1 for update NOWAIT ;
## 针对多个数据,如果有数据被锁定,则不返回被锁定的数据,即跳过被锁定的数据
select * from tableXX where   SKIP LOCKED ;

6.7 索引并行读取

从MySQL 8.0.14开始,InnoDB支持并行聚集索引读取,这可以提高 CHECK TABLE性能。此功能不适用于二级索引扫描

6.8 其它的改进

  1. 快速的DDL, alter table
  2. 默认字符集已从更改 latin1为utf8mb4。
  3. InnoDB 临时表空间,使用共享的临时表空间ibtmp1
  4. 新增索引换成页数
  5. EXPLAIN ANALYZE语句。 MySQL 8.0.18中实现了 一种新形式的EXPLAIN 语句,它以处理查询所使用的每个迭代器的格式EXPLAIN ANALYZE提供了有关SELECT语句 执行的扩展信息 TREE,并使得可以将估计成本与查询的实际成本进行比较。该信息包括启动成本,总成本,此迭代器返回的行数以及执行的循环数。
  6. INFORMATION_SCHEMA.INNODB_CACHED_INDEXES
    新引入的表,用来查看每个索引在InnoDB缓冲池中缓存的索引页数。



##1- limit 限制几个
select * from user limit 55
select * from user limit 55 ,5 从第五个开始,限制55个

2 - between A and B 在AB中间的值都行 ,in只能括号是其中的值

3-空值查询 XXX IS NULL 或者 XXX IS NOT NULL

4- NOT

SELECT u.id from sys_user   u where  u.id  NOT IN (1,20) 
SELECT u.id from sys_user   u where  u.id   NOT BETWEEN   1 AND 5

5-LIKE 注意三个的区别,下划线_ 只能匹配一个字符,%匹配多个

SELECT u.user_name from sys_user   u where  u.user_name LIKE '%hcg%'

SELECT u.user_name from sys_user   u where  u.user_name LIKE 'hcg%'

SELECT u.user_name from sys_user   u where  u.user_name LIKE '%hcg'

SELECT u.user_name from sys_user   u where  u.user_name LIKE '_hcg'

但是不能过度使用通配符,如果有需要放在排序的最后面,因为它的查询速度非常慢

6-正则表达式

  // 查询含文本hcg的所有值
  SELECT u.user_name from sys_user   u where  u.user_name REGEXP 'hcg'
  //. 能匹配任意一个字符
  SELECT u.user_name from sys_user   u where  u.user_name REGEXP '.hcg'

  //mysql 的正则表达式匹配不区分大小写,即无论是什么匹配的既有大写也有小写
  //解决方案是 加一个关键字: BINARY  后面跟的是大写匹配大写,如果是小写匹配小写
  SELECT u.user_name from sys_user   u where  u.user_name REGEXP BINARY 'U'
  SELECT u.user_name from sys_user   u where  u.user_name REGEXP  'U'

  // | 是OR的意思即或   同时如果前面有BINARY 关键字 匹配的是里面的值,比如下面匹配的都是
  //小写的u 和大写H
  SELECT u.user_name from sys_user   u where  u.user_name REGEXP  BINARY 'u|H'

  //[123]里面可以放一些字符,表示随便匹配其中的一个,事实上他是[1|2|3]的缩写
  SELECT u.user_name from sys_user   u where  u.user_name REGEXP  BINARY 'r[123]'

  //[X-X]表示一个集合 [1-3]相当于[1|2|3]
  SELECT u.user_name from sys_user   u where  u.user_name REGEXP  BINARY '[0-9]'
  //这里因为.能匹配任意一个字符,所以这里想要匹配带.的要用转译符  // 
  SELECT u.user_name from sys_user   u where  u.user_name REGEXP  BINARY '.'
  SELECT u.user_name from sys_user   u where  u.user_name REGEXP  BINARY '//.'
  //那么问题来了,怎么匹配/  这里用三个/就好了 
   SELECT u.user_name from sys_user   u where  u.user_name REGEXP  BINARY '///'
   //{n}最靠近它左边的值要求被匹配的次数
   //{n,}不少于指定数目的匹配
   //{n,m}匹配数目的范围,m不超过255
   //{*}0个或者多个匹配
   //{+}1个或者多个匹配
   //{?}0个或者1个


   //如果想要以一个数字开始,而上面的所有都没有这个属性,都是在任意位置都可以,为了解决这个问题,定位符出现了,它可以指定位置
   ^ 文本的开始
   $ 文本的结尾
   [[:<:]]词的开始
   [[:<:]]词的结尾 
 // ^有两种用法,一个是限定的开始,一个是否定一个集合
     [^a]表示“匹配除了a的任意字符”。
     [^a-zA-Z0-9]表示“找到一个非字母也非数字的字符”





7-REGEXP 和LIKE 的区别在于like匹配的是整个字符串而REGEXP匹配的是子串,但是可以用^ $起到和like相同的作用,而同样LIKE也可以用 % %起到REGEXP的作用。


//同时正则表达式的书写其实不用数据库,因为REGEXP的查询总是返回0或者1
SELECT 'hello' REGEXP '[0-9]'

8- 常使用的函数

// CONCAT 函数是拼接函数,需要被拼接的列用逗号隔开即可
SELECT CONCAT(u.user_name ,u.email ) FROM sys_user u WHERE u.id < 10
//还可以在中间或者任意位置放置你想要的连接符
SELECT CONCAT(u.user_name , '============',u.email ) FROM sys_user u WHERE u.id < 10

//RTrim()  LTrim()去掉值右边、左边的空格
SELECT CONCAT( RTRIM (u.user_name) , '============', LTRIM(u.email) ) FROM sys_user u WHERE u.id < 10
// *—+/ 这些算数运算符也是可以直接用的
SELECT (u.`status` * u.role_id) AS HH  FROM sys_user u  WHERE  u.id <10



你可能感兴趣的:(MySql)