相关数据库排名:https://db-engines.com/en/ranking
官网地址:https://www.mysql.com
属于Oracle旗下的产品
支持多线程、体积小、速度快、提供多语言支持、支持多种操作系统、为各种变成语言提供API语言、使用标准的SQL数据语言形式
CREATE DATABASE [IF NOT EXISTS] <数据库名> [[DEFAULT] CHARACTER SET <字符集> | [DEFAULT] COLLATE <校对规则名>];
示例:
CREATE DATABASE IF NOT EXISTS TEST CHARACTER SET utf8;
SHOW DATABASES [LIKE <数据库名>];
示例:
SHOW DATABASES LIKE TEST;
ALTER DATABASE [数据库名] {[DEFAULT] CHARACTER SET <字符集> | [DEFAULT] COLLECT <校对规则名>};
示例:
ALTER DATABASE TEST CHARACTER SET utf8;
DROP DATABASE [IF EXISTS] <数据库名>;
示例:
DROP DATABASE IF EXISTS TEST;
USE DATABASE_NAME; -- 切换数据库
SELECT DATABASE(); -- 查看数据库
DESC TABLE_NAME; -- 查看表结构
一般使用utf8mb4字符集
SHOW VARIABLES LIKE '%char%'; -- 查看字符集
SHOW CREATE DATABASE TEST; -- 查看数据库创建语句
提升查询效率
在创建于语句加TEMPORARY,例如
CREATE TEMPORARY TABLE TEST2(ID INT(2)); -- 创建
INSERT INTO TEST2 SELECT * FROM TEST; -- 使用
SELECT * FROM TEST2 GROUP BY * ORDER BY *; -- 查询
备注:临时表不会出现在数据库中,且只会在当前session生效。
CREATE TABLE A LIKE B; -- 仅创建表结构
CREATE TABLE A SELECT * FROM B [WHERE ****]; -- 创建表结构和复制数据
先修改原表名,再创建相同的表
RENAME TABLE A TO B; -- 修改原表名
CREATE TABLE B LIKE A; -- 仅创建表结构
-- DML;会留存记录,产生大量日志,可以回滚;执行后会返回结果(删除多少条);仅是删除数据
DELETE FROM TABLE_NAME;
-- DDL;不留日志,无法回滚;执行后不会返回结果(仅返回0);从结构上完全重置
TRUNCATE TABLE TABLE_NAME;
INSERT IGNORE INTO ****; -- 如果存在重复数据,则忽略,并返回0,否则返回成功条数
REPLACE INTO ****; -- 如果存在重复数据,则更新,否则插入
INSERT INTO TEST2 SELECT * FROM TEST; -- 不能再操作TEST表,会锁死TEST表;进操作小数据量(不超1w)
HELP 'CREATE%';
SELECT * FROM MYSQL.HELP_TOPIC WHERE NAME LIKE '%BETWEEN%';
TYPE | STORAGE(BYTES) | MINIMUM VALUE SIGNED | MINIMUM VALUE UNSIGNED | MAXIMUM VALUE SIGNED | MAXIMUM VALUE UNSIGNED |
---|---|---|---|---|---|
TINYINT | 1 | -128 | 0 | 127 | 255 |
SMALLINT | 2 | -32768 | 0 | 32767 | 65535 |
MEDIUMINT | 3 | -8388608 | 0 | 8388607 | 16777215 |
INT | 4 | -2147483648 | 0 | 2147483647 | 4294967295 |
BIGINT | 8 | − 2 63 -2^{63} −263 | 0 | 2 63 − 1 2^{63}-1 263−1 | 2 64 − 1 2^{64}-1 264−1 |
备注:
TYPE | STORAGE(BYTES) | MINIMUM VALUE SIGNED | MINIMUM VALUE UNSIGNED | MAXIMUM VALUE SIGNED | MAXIMUM VALUE UNSIGNED |
---|---|---|---|---|---|
FLOAT | 4 | -3.40E+38 | 0和-1.18E-38 | -1.18E-38 | -3.40E+38 |
DOUBLE | 8 | -1.80E+308 | 0和-2.23E-308 | -2.23E-308 | -1.80E+308 |
DECIMAL(M,D) | M+2 | 同上 | 同上 | 同上 | 同上 |
备注:
TYPE | STORAGE(BYTES) | MINIMUM VALUE | MINIMUM VALUE | ZERO VALUE | FORMATE |
---|---|---|---|---|---|
YEAR | 1 | 1901 | 2155 | 0 | YYYY |
TIME | 3 | -838:59:59 | 838:59:59 | 00:00:00 | HH:MM:SS |
DATE | 3 | 1000-01-01 | 9999-12-31 | 0000-00-00 | YYYY-MM-DD |
DATETIME | 8 | 1000-01-01 00:00:00 | 9999-12-31 23:59:59 | 0000-00-00 00:00:00 | YYYY-MM-DD HH;MM;SS |
TIMESTAMP | 4 | 1970-01-01 00:00:01UTC | 2038-01-19 03:14:07UTC | 0000-00-00 00:00:00 | YYYY-MM-DD HH;MM;SS |
DATETIME |
备注:
-- timestamp可以在更新的时候自动更新
-- timestamp时间有限,因此5.6升级成了datetime
CREATE TABLE TIMETEST(
`ID` INT(11) NOT NULL AUTO_INCREMENT,
`TIMESTAMP_COL` TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`DATETIME_COL` DATETIME DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`ID`)
) ENGINE=INNODB DEFAULT CHARSET=UTF8;
TYPE | STORAGE(BYTES) | DESC |
---|---|---|
CHAR(m) | 255 | 固定长度非二进制字符串 |
VARCHAR(m) | 0~65535 | 变长非二进制字符串 |
TINYTEXT | 2 8 − 1 2^{8}-1 28−1 | 非常小的非二进制字符串 |
TEXT | 2 16 − 1 2^{16}-1 216−1 | 小的非二进制字符串 |
MEDIUMTEXT | 2 24 − 1 2^{24}-1 224−1 | 中等大小的非二进制字符串 |
LONGTEXT | 2 32 − 1 2^{32}-1 232−1 | 大的非二进制字符串 |
ENUM | 65535 | 枚举类型 |
SET | 64 | 一个集合,可以有0个或多个成员 |
值 | 索引 |
---|---|
NULL | NULL |
‘’ | ‘0’ |
‘A’ | 1 |
‘B’ | 2 |
‘C’ | 3 |
CREATE TABLE TIMETEST(
`ID` INT(11) NOT NULL AUTO_INCREMENT,
`ENUM_COL` ENUM('A','B','C') DEFAULT NULL, --只能是字符串,最大长度65535
PRIMARY KEY (`ID`)
) ENGINE=INNODB DEFAULT CHARSET=UTF8;
值 | 索引 |
---|---|
NULL | NULL |
‘’ | ‘0’、0 |
‘A’ | 1 |
‘B’ | 2 |
‘A’,‘B’ | 3 |
‘C’’ | 3 |
CREATE TABLE TIMETEST(
`ID` INT(11) NOT NULL AUTO_INCREMENT,
`ENUM_COL` SET('A','B','C') DEFAULT NULL, --只能是字符串,最大长度64
PRIMARY KEY (`ID`)
) ENGINE=INNODB DEFAULT CHARSET=UTF8;
备注:
-- 求长度
SELECT LENGTH(); -- 求占了多少字节
SELECT CHAR_LENGTH(); -- 仅求字符个数
-- 字符串转换,都只处理第一位
SELECT ASCII();
SELECT ORD();
-- ASCII转换回字符
SELECT CHAR();
-- 拼接,不能有空格
SELECT CONCAT('ARE', 'YOU', 'OK');
-- 分割符拼接
SELECT CONCAT_WS('*', 'ARE', 'YOU', 'OK');
-- 返回第一个字符串s在字符串列表(s1,s2……)中的位置;全匹配;null无法匹配
SELECT FIELD('A', 'CDE', 'ABC', 'MMM');
-- 查找字符串s1在集合中的位置,集合只能用逗号分隔
SELECT FIND_IN_SET('A', 'A,B,C');
-- 查找字符串位置;没有找到返回0,对于null返回null
SELECT LOCATE('AB', 'AB AND');
SELECT POSITION('AB' IN 'AB AND');
-- 左右截取
SELECT LEFT('ARE', 1);
SELECT RIGHT('ARE', 1);
-- 任意位置截取
SELECT MID ('AREDC', 1, 3);
SELECT SUBSTR ('AREDC', 1, 3);
SELECT SUBSTR ('AREDC' FROM 1 FOR 3);
SELECT SUBSTR ('AREDC', 3);
SELECT SUBSTR ('AREDC' FROM 3);
SELECT SUBSTRING('AREDC', 1, 3);
SELECT SUBSTRING('AREDC' FROM 1 FOR 3);
SELECT SUBSTRING('AREDC', 3);
SELECT SUBSTRING('AREDC' FROM 3);
-- 正数返回前面的所有内容,复数返回后面的所有内容
SELECT SUBSTRING_INDEX('A*B*C*D', '*', 1);
-- 替换字符串
SELECT REPLACE('ABVCDE', 'ABV', 'ABC');
SELECT INSERT('HELLO', 2, 2, 'AA')
-- 逆向
SELECT REVERSE('ABCD');
-- 大小写转换
SELECT LCASE('ABCD');
SELECT LOWER('ABCD');
SELECT UCASE('abcd');
SELECT UPPER('abcd');
-- 左右填充
SELECT LAPD('ABC', 6, '0');
SELECT RPAD('ABC', 6, '0');
-- 去空格
SELECT LTRIM(' ABC');
SELECT RTRIM('ABC ');
SELECT TRIM(' ABC ');
-- 数字格式化
SELECT FORMAT(1223.455677, 2);
-- 字符串插入
SELECT INSERT('HELLO', 2, 0, 'AA');
-- 大小对比
SELECT STRCMP('ABC', 'ABD');
-- 绝对值
SELECT ABS(-12);
-- 向上取整,返回大于等于的最小整数
SELECT CELL(1.3);
-- 向下取整,返回小于等于的最大整数
SELECT FLOOR(1.3);
-- 四舍五入和截取(精确到小数点后几位)
SELECT ROUND(1.234, 2);
SELECT TRUNCATE(1.234, 2);
-- 查询表的记录数
SELECT COUNT(*) FROM TEST;
SELECT COUNT(1) FROM TEST;
SELECT COUNT(COL_NAME) FROM TEST;
SELECT COUNT(DISTINCT COL_NAME) FROM TEST;
-- 最大最小值
SELECT GREATEST(COL_NAME1, COL_NAME2) FROM TEST; -- 横向对比最大值
SELECT LEATEST(COL_NAME1, COL_NAME2) FROM TEST; -- 横向对比最小值
SELECT MAX(COL_NAME) FROM TEST; -- 纵向对比最大值
SELECT MIN(COL_NAME) FROM TEST; -- 纵向对比最小值
-- 求和、平均值
SELECT SUM(COL_NAME) FROM TEST;
SELECT AVG(COL_NAME) FROM TEST;
-- 取余
SELECT MOD(10, 7);
-- 随机数
SELECT RAND();
SELECT CURDATE();
SELECT CURRENT_DATE; -- 同CURDATE
SELECT CURRENT_DATE(); -- 同CURDATE
SELECT CURTIME();
SELECT CURRENT_TIME; -- 同CURTIME
SELECT CURRENT_TIME(); -- 同CURTIME
SELECT NOW();
SELECT NOW(6); -- 同NOW
SELECT CURRENT_TIMESTAMP; -- 同NOW
SELECT CURRENT_TIMESTAMP(); -- 同NOW
SELECT CURRENT_TIMESTAMP(3); -- 同NOW
SELECT LOCALTIME; -- 同NOW
SELECT LOCALTIMESTAMP; -- 同NOW
SELECT LOCALTIME(3); -- 同NOW
SELECT LOCALTIMESTAMP(6); -- 同NOW
SELECT SYSDATE(); -- 不推荐使用
-- SYSDATE()是基于系统当前时间,其他的是语句执行时间
-- 加减天
SELECT ADDDATE(NOW(), 10);
SELECT SUBDATE(NOW(), 10);
-- 加减时间
SELECT ADDTIME(NOW(), '1:1:1');
SELECT SUBTIME(NOW(), '1:1:1');
-- 日期差
SELECT DATEDIFF(NOW(), '2021-12-12');
-- 时间差
SELECT TIMEDIFF(2021-12-13 00:00:00, '2021-12-12 00:00:00');
-- 月份差,加
SELECT PERIOD_DIFF(202112, 202111);
SELECT PERIOD_ADD(202112, 1);
-- 提取日期、时间、年月日时分秒、毫秒、季度、星期、周数
SELECT
DATE(NOW(6)) '日期',
TIME(NOW(6)) '日期',
YEAR(NOW(6)) '年',
MONTH(NOW(6)) '月',
DAY(NOW(6)) '天',
HOUR(NOW(6)) '时',
MINUTE(NOW(6)) '分钟',
SECOND(NOW(6)) '秒',
MICROSECOND(NOW(6)) '毫秒',
QUARTER(NOW(6)) '季度',
WEEKDAY(NOW(6)) '星期几(0为星期一)',
YEARWEEK(NOW(6)) '年和周数';
-- 根据类型进行提取
SELECT EXTRACT(YEAR FROM NOW());
-- 计算日期为年、周、月的第几天
SELECT
DAYOFYEAR(NOW()) '当年的第几天',
DAYOFWEEK(NOW()) '当周的第几天,周日为第一天',
DAYOFMONTH(NOW()) '当月的第几天',
WEEK(NOW()) '当年的第几周,从0开始',
WEKKOFYEAR(NOW()) '当年的第几周,从1开始';
-- 构建日期、构建时间
SELECT
MAKEDATE(2020, 50) '2020年第50天',
MAKETIME(12, 23, 23) '构建时间';
-- 秒的换算
SELECT
SEC_TO_TIME(2000) '秒换算成时分秒',
TIME_TO_SEC('2:20:00') '时分秒换算成秒';
-- 格式转换
SELECT STR_TO_DATE('2020-12-29 12:12:12.123', '%Y-%m-%d %H:%i:%s.%f');
SELECT DATE_FORMAT(NOW(6), '%Y-%m-%d %H:%i:%s.%f');
-- 查找数据是否存在集合中
SELECT 1 IN (1,2,3);
-- 返回第一个非空数据
SELECT COALESCE(NULL, 'A', 'B');
-- 返回第一个大于n的索引位置,索引从0开始
SELECT INTERVAL(5, 1, 2, 3, 4, 5, 6, 7);
-- 流程函数
SELECT
IF (2 > 1, 'AAA', 'BBB'),
IF (2 > 3, COL_NAME1, COL_NAME2)
FROM
TEST LIMIT 1O;
SELECT IFNULL(COL_NAME1, COL_NAME2);
SELECT 10 DIV 3, 10/3; -- 整除
SELECT CHARSER('A'); -- 查看字符集
SELECT
CONNECTION ID() '当前连接ID',
USER() '当前用户',
CURRENT_USR() '当前用户',
DATABASE() '当前数据库';
SELECT FOUND_ROWS(); -- 查询上次查询的行数(不使用)
SELECT
ROW_COUNT() '查询上次插入影响的行数(不使用)',
LAST_INSERT_ID() '查询上次插入查询的行数(不使用)';
-- 行转列
GROUP_CONCAT([DISTINCT] 要连接得字段 [ORDER BY 排序字段 ASC/DESC] [SEPARATOR '分隔符'])
-- 加密和解密
-- 对称加密
SELECT AES_ENCRYPT('SJJSK', '密钥');
SELECT AES_DECRYPT(AES_ENCRYPT('SJJSK', '密钥'), '密钥');
-- HASH算法:
SELECT
MD5('123456'),
SHA('123456'),
SHA1('123456'),
SHA2('123456'),
SHA2('123456', 224),
SHA2('123456', 256),
SHA2('123456', 384),
SHA2('123456', 512),
SHA2('123456', 0);
-- 压缩和解压
SELECT COMPRESS('SLJKFJSLKFJL');
SELECT UNCOMPRESS(COMPRESS('SLJKFJSLKFJL'));
-- 锁函数
SELECT GET_LOCK('USER1', 10); -- 加锁
SELECT RELEASE_LOCK('USER1'); -- 释放锁
SELECT IS_FREE_LOCK('USER1'); -- 是否释放锁
SELECT IS_USED_LOCK('USER1'); -- 锁是否被使用
-- 查看引擎
SHOW ENGINES;
SELECT * FROM INFORMATION_SCHEMA.ENGINES;
SHOW VARIABLES LIKE '%ENGIN%';
-- 设置引擎
-- 仅对当前会话有用
SET SESSION DEFAULT_STORAGE_ENGINE=INNODB;
SET DEFAULT_STORAGE_ENGINE=MYISAM;
-- 仅对新开得会话
SET GLOBAL DEFAULT_STORAGE_ENGINE=MYISAM;
-- 如果新开不会生效,需要修改配置后重启
linux->my.cnf或者window->my.ini
备注:不允许在最大值前,插入数据,例如数据库中有2条数据,id=1和10,插入的时候不能插入id=2~9之间的数据,只能追加数据
-- 查看逻辑存储结构
SHOW VARIABLES LIKE '%INNODB_FILE_PER_TABLE%';
4. 可以进行范围查找,例如查找15~30之间的数据,根据指针就可以很容易找到
-- 查看dml语句执行次数
SHOW GLOBAL STATUS;
EXPLAIN sql语句;
id相同时从上往下,id不同时从下往上
表名
分区
可能使用到的索引
真正使用到的索引
索引长度
扫描多少行
扫描了百分比数据
额外的信息
必须在命令行使用,客户端会观察不到
-- 查看参数
SHOW VARIABLES LIKE '%PROFILING%'
-- 开启
SET PROFILING=ON;
-- 显示query耗时
SHOW PROFILES;
-- 显示每一步的执行耗时,其中sending data占时长,是从整理到打包到发送给客户端整个流程
SHOW PROFILE FOR QUERY 1;
-- 查看查询次数和缓存查询次数
SHOW GLOBAL STATUS WHERE VARIABLE_NAME IN ('QCACHE_HITS', 'COM_SELECT');
-- 使用缓存查询
SELECT SQL_CACHE * FROM TABLE_NAME WHERE COL_NAME = '';
-- 不使用缓存查询
SELECT SQL_NO_CACHE * FROM TABLE_NAME WHERE COL_NAME = '';
-- 查看一个表得索引
SHOW INDEX FROM TABLE_NAME;
-- 创建索引
CREATE INDEX INDEX_NAME ON TABLE_NAME(COL_NAME, COL_NAME);
创建了一个复合索引A_B_C,相当于创建了A,A_B,A_B_C三个索引。所以最左是指,创建的复合索引,最左边的索引会生效,如果单独用B或B_C来查数据,索引是不生效的。
使用>, >=等范围查找,会使右侧的索引失效。这里的右侧是以索引的创建循序。
尽量使用覆盖索引,减少对select *的使用,也不要查询不使用的字段。尽量查询结果都从索引字段中获取,目的是减少回表操作。
or语句只要有一个没有走索引(即索引的一部分)就会导致索引失效。
%仅加在最右侧才能使用到索引
相同列中,区分度大的数据走索引,区分度小的数据走全表扫描(主要是数据的分布i情况)
本质上是符合区分度
in会使用索引,not in不会使用索引,避免使用not in
尽量使用复合索引少使用单列索引,当有多个索引可以使用的时候,数据库会选择一个最优的索引来使用。
在进行字段对比,多表关联的时候,必须保证数据类型相同,否则会触发隐式的类型转换,可能会导致索引失效。
同in与not in
使用load方法导入数据,数据尽量是有序的或者自增的。
-- load数据导入
LOAD DATA LOCAL INFILE '文件位置' INTO TABLE TABLE_NAME FIELDS TERMINATED BY ',' LINES TERMINATED BY '\r\n';
-- 导入数据前关闭唯一性校验,数据导入完成后,再开启
SET UNIQUE_CHECKS = OFF;
SET UNIQUE_CHECKS = ON;
SET AUOTCOMMIT = OFF;
SET AUOTCOMMIT = ON;
减少单条语句插入方式,反而使用批量方式。
-- 缓冲区
SHOW VARIABLES LIKE '%sort_buffer_size%';
-- 字段长度大小
SHOW VARIABLES LIKE '%max_length_for_sort_data%';
group by是先进行排序,在进行分组,排序之后再使用一些聚合函数进行计算,所以同order by的优化原则。
使用表关联来代替子查询
在进行分页查询使用。
SELECT * FROM TEST LIMIT 1999999, 10;
SELECT * FROM TEST A, (SELECT ID FROM TEST LIMIT 1999999, 10) B WHERE A.ID = B.ID;
SELECT * FROM TEST WHERE ID >= 1999999 AND ID < 1999999+10;
-- 建议使用索引
SELECET COL_NAME FROM TABLE_NAME USE INDEX(INDEX_NAME);
-- 忽略使用索引
SELECET COL_NAME FROM TABLE_NAME IGNORE INDEX(INDEX_NAME);
-- 强制使用索引
SELECET COL_NAME FROM TABLE_NAME FORCE INDEX(INDEX_NAME);
-- 创建TEST1表
CREATE TABLE `TEST1`
(
`ID` INT(10) NOT NULL,
`NAME` VARCHAR(50) NOT NULL
) ENGINE = MyISAM
DEFAULT CHARSET = UTF8;
-- 创建TEST2表
CREATE TABLE TEST2 LIKE TEST1;
-- 创建插入方式为first方法的TEST_MERGE_FIRST表
CREATE TABLE `TEST_MERGE_FIRST`
(
`ID` INT(10) NOT NULL,
`NAME` VARCHAR(50) NOT NULL
) ENGINE = MRG_MyISAM
DEFAULT CHARSET = UTF8
INSERT_METHOD = FIRST
UNION = (TEST1, TEST2);
-- 创建插入方式为last方法的TEST_MERGE_LAST表
CREATE TABLE `TEST_MERGE_LAST`
(
`ID` INT(10) NOT NULL,
`NAME` VARCHAR(50) NOT NULL
) ENGINE = MRG_MyISAM
DEFAULT CHARSET = UTF8
INSERT_METHOD = LAST
UNION = (TEST1, TEST2);
-- 创建不定义插入方式的TEST_MERGE_DEFAULT表
CREATE TABLE `TEST_MERGE_DEFAULT`
(
`ID` INT(10) NOT NULL,
`NAME` VARCHAR(50) NOT NULL
) ENGINE = MRG_MyISAM
DEFAULT CHARSET = UTF8
UNION = (TEST1, TEST2);
-- 查看分区
SHOW PLUGINS;
-- 创建分区表
CREATE TABLE `TEST`
(
`ID` INT(10) NOT NULL AUTO_INCREMENT,
`NAME` VARCHAR(50) NOT NULL,
PRIMARY KEY (ID)
) ENGINE = InnoDB
DEFAULT CHARSET = UTF8
PARTITION BY HASH (ID) -- 自增主键用来分区(含有即可)
PARTITIONS 4; -- 分区数量
-- 查看分区表
SELECT * FROM INFORMATION_SCHEMA.PARTITIONS WHERE TABLE_SCHEMA = database() AND PARTITION_NAME IS NOT NULL AND TABLE_NAME = 'TEST';
-- 创建分区表
CREATE TABLE `TEST`
(
`ID` INT(10) NOT NULL AUTO_INCREMENT,
`NAME` VARCHAR(50) NOT NULL,
PRIMARY KEY (ID)
) ENGINE = InnoDB
DEFAULT CHARSET = UTF8
PARTITION BY LINEAR HASH (ID) -- 自增主键用来分区(含有即可)
PARTITIONS 4; -- 分区数量
-- 创建KEY分区表
CREATE TABLE `TEST`
(
`ID` INT(10) NOT NULL AUTO_INCREMENT,
`NAME` VARCHAR(50) NOT NULL,
PRIMARY KEY (ID, NAME) -- 联合主键
) ENGINE = InnoDB
DEFAULT CHARSET = UTF8
PARTITION BY KEY (ID) -- 指定要分区的列,必须为主键或非空唯一索引列(含有即可)
PARTITIONS 4;
-- 创建线性KEY分区表
CREATE TABLE `TEST`
(
`ID` INT(10) NOT NULL AUTO_INCREMENT,
`NAME` VARCHAR(50) NOT NULL,
PRIMARY KEY (ID, NAME)
) ENGINE = InnoDB
DEFAULT CHARSET = UTF8
PARTITION BY KEY (ID) -- 指定要分区的列,必须为主键或非空唯一索引列(含有即可)
PARTITIONS 4;
-- 创建线性RANGE分区表
CREATE TABLE `TEST`
(
`ID` INT(10) NOT NULL AUTO_INCREMENT,
`DATE` DATE NOT NULL,
`NAME` VARCHAR(50) NOT NULL,
PRIMARY KEY (ID, DATE)
) ENGINE = InnoDB
DEFAULT CHARSET = UTF8
PARTITION BY RANGE (year(DATE)) ( -- 必须返回的是整数
PARTITION P0 VALUES LESS THAN (1990),
PARTITION P1 VALUES LESS THAN (2000),
PARTITION P2 VALUES LESS THAN (2010),
PARTITION P3 VALUES LESS THAN (2020),
PARTITION P4 VALUES LESS THAN MAXVALUE);
-- 查询数据
SELECT * FROM TEST PARTITION (p0);
-- 查看各种信息
SELECT TABLE_NAME,
PARTITION_NAME '分区名字',
SUBPARTITION_NAME '子分区名字',
PARTITION_ORDINAL_POSITION '分区顺序',
SUBPARTITION_ORDINAL_POSITION '子分区顺序',
PARTITION_METHOD '分区方法',
SUBPARTITION_METHOD '子分区方法',
PARTITION_EXPRESSION '分区表达式',
SUBPARTITION_EXPRESSION '子分区表达式',
PARTITION_DESCRIPTION '分区描述',
TABLE_ROWS '数据行数'
FROM INFORMATION_SCHEMA.PARTITIONS
WHERE TABLE_SCHEMA = DATABASE()
AND PARTITION_NAME IS NOT NULL
AND TABLE_NAME = TEST;
-- 创建线性List分区表
CREATE TABLE `TEST`
(
`ID` INT(10) NOT NULL AUTO_INCREMENT,
`DATE` DATE NOT NULL,
`NAME` VARCHAR(50) NOT NULL,
PRIMARY KEY (ID, DATE)
) ENGINE = InnoDB
DEFAULT CHARSET = UTF8
PARTITION BY LIST (year(DATE)) ( -- 必须返回的是整数
PARTITION P0 VALUES IN (1999, 2000, 2001), -- 使用IN表示分区范围
PARTITION P1 VALUES IN (2020, 2023));
-- 查询数据
SELECT * FROM TEST PARTITION (p0);
-- 创建线性COLUMNS分区表(单字段)
CREATE TABLE `TEST`
(
`ID` INT(10) NOT NULL AUTO_INCREMENT,
`DATE` DATE NOT NULL,
`NAME` VARCHAR(50) NOT NULL,
PRIMARY KEY (ID, DATE)
) ENGINE = InnoDB
DEFAULT CHARSET = UTF8
PARTITION BY RANGE COLUMNS (DATE)(
PARTITION P0 VALUES LESS THAN ('1980-10-01'),
PARTITION P1 VALUES LESS THAN ('1990-10-01'),
PARTITION P2 VALUES LESS THAN ('2000-10-01')
);
-- 创建线性COLUMNS分区表(多字段)
CREATE TABLE `TEST`
(
`ID` INT(10) NOT NULL,
`DATE` DATE NOT NULL,
`NAME` VARCHAR(50) NOT NULL
) ENGINE = InnoDB
DEFAULT CHARSET = UTF8
PARTITION BY RANGE COLUMNS (ID, DATE)(
PARTITION P0 VALUES LESS THAN (1000, '1980-10-01'),
PARTITION P1 VALUES LESS THAN (2000, '1990-10-01'),
PARTITION P2 VALUES LESS THAN (3000, '2000-10-01'),
PARTITION P3 VALUES LESS THAN (MAXVALUE , MAXVALUE )
);
-- 创建子分区(第一种方式)
CREATE TABLE `TEST`
(
`ID` INT(10) NOT NULL,
`DATE` DATE NOT NULL,
`NAME` VARCHAR(50) NOT NULL
) ENGINE = InnoDB
DEFAULT CHARSET = UTF8
PARTITION BY RANGE (year(DATE))
SUBPARTITION BY HASH (year(DATE))
SUBPARTITIONS 2
(
PARTITION P0 VALUES LESS THAN (1980),
PARTITION P1 VALUES LESS THAN (1990),
PARTITION P2 VALUES LESS THAN (2000),
PARTITION P3 VALUES LESS THAN (MAXVALUE)
);
-- 创建子分区(第二种方式)
CREATE TABLE `TEST`
(
`ID` INT(10) NOT NULL,
`DATE` DATE NOT NULL,
`NAME` VARCHAR(50) NOT NULL
) ENGINE = InnoDB
DEFAULT CHARSET = UTF8
PARTITION BY RANGE (year(DATE))
SUBPARTITION BY HASH (year(DATE))
(
PARTITION P0 VALUES LESS THAN (1980)(
SUBPARTITION S1,
SUBPARTITION S2
),
PARTITION P1 VALUES LESS THAN (1990)(
SUBPARTITION S3,
SUBPARTITION S4
),
PARTITION P2 VALUES LESS THAN (2000)(
SUBPARTITION S5,
SUBPARTITION S6
),
PARTITION P3 VALUES LESS THAN (MAXVALUE)(
SUBPARTITION S7,
SUBPARTITION S8
)
);
-- 查看当前数据库分区表信息(全部)同上面的部分信息
SELECT * FROM INFORMATION_SCHEMA.PARTITIONS WHERE TABLE_SCHEMA = database() AND PARTITION_NAME IS NOT NULL;
-- 按照单分区查
SELECT * FROM TEST PARTITION (p0);
-- 按照多分区查
SELECT * FROM TEST PARTITION (p0, P1, P2);
-- 新增分区
ALTER TABLE TEST ADD PARTITION (PARTITION P6 VALUES LESS THAN (2020));
一般不写MAXVALUE,这样就会导致大于最大值后,数据全部分布到最后一个分区
-- 调整分区数量
ALTER TABLE TEST PARTITION BY HASH ( ID ) PARTITIONs 5;
ALTER TABLE TEST COALESCE PARTITION 3; -- 合并3个分区,假设原来5个分区,执行后,就剩下2个分区,不建议用
会自动将数据分配到调整后的分区
可以将多个分区合并成一个,也可以将一个分区拆成多个
-- 将P3分区拆成两个
ALTER TABLE TEST REORGANIZE PARTITION P3 INTO (
PARTITION P31 VALUES LESS THAN (2010),
PARTITION P32 VALUES LESS THAN (MAXVALUE)
);
-- 将多个分区合成一个:仅能使用最大分区的值
ALTER TABLE TEST REORGANIZE PARTITION P1, P2 INTO (
PARTITION P31 VALUES LESS THAN (2000),
);
-- 将3个分区拆成2个分区:必须是连续分区
ALTER TABLE TEST REORGANIZE PARTITION P1, P2, P3 INTO (
PARTITION P31 VALUES LESS THAN (2000),
PARTITION P31 VALUES LESS THAN (2010)
);
-- 常用来数据清理,适合用来清理不用分区的数据
ALTER TABLE TEST TRUNCATE PARTITION P0;
ALTER TABLE TEST TRUNCATE PARTITION P0, P1;
-- 分析分区:读取和存储分区中值的分布情况
ALTER TABLE TEST ANALYZE PARTITION P1, P2;
-- 检查分区:检查分区中是否存在错误
ALTER TABLE TEST CHECK PARTITION P1, P2;
-- 修复分区:修复被损坏的分区
ALTER TABLE TEST REPAIR PARTITION P1, P2;
-- 优化分区:相当于执行了上面3个,主要用于回收空闲空间和分区的碎片整理
ALTER TABLE TEST OPTIMIZE PARTITION P1, P2;
-- 转换成hash分区表,其他的类似
ALTER TABLE TEST PARTITION BY HASH ( ID ) PARTITIONS 4;
SHOW VARIABLES LIKE '%SLAVE%'
MTS是从5.6版本后支持的。
5.6版本支持的是:库级别的同步——global.slave_parallel_type = ‘DATABASE’
5.7版本支持的是:
① 行级别的同步——global.slave_parallel_type = ‘LOGICAL_CLOCK’
——global.slave_parallel_type = ‘DATABASE’(默认值)
② coordinater+workers模型:规则1更新同一个数据中的多个事务,必须提交给同一个worker执行。规则2同一个事务不同SQL语句,不可以分发给不同的worker。规则1/2是为了避免数据错乱。
③ 组提交
binlog和redolog结合解决数据库崩溃恢复问题
redolog和relaylog是InnoDB引擎独有的日志
error log日志:如果在服务运行期间,被关闭就不回生成,因为它仅记录服务的启动、停止、运行中的错误
general log日志:如果是客户端连接,会记录下相关的连接、执行的sql等其他日志
-- 查询配置
SHOW VARIABLES LIKE '%slow_query%';
-- 查询多长算慢
SHOW VARIABLES LIKE '%long_query_time%';
记录顺序:不一定是先执行先记录,是在select执行完毕后,释放所有资源后,开始记录的
日志分析:mysqldumpslow ***slow.log
-- 查询binlog配置
SHOW VARIABLES LIKE '%binlog%';
-- 文件相关位置
SHOW VARIABLES LIKE '%log_bin%';
日志分析:mysqlbinlog ***bin.log
和binlog日志结合,避免crash safe
该日志文件由两部分组成:重做日志缓冲(redo log buffer)以及重做日志文件(redo log file),前者是在内存中,后者在磁盘中。当事务提交之后会把所有修改信息都存到该日志文件中, 用于在刷新脏页到磁盘,发生错误时, 进行数据恢复使用,从而保持持久性。
undo log记录的是逻辑日志(即每一步执行的是什么样子的操作)。
当delete一条记录时,undo log中会记录一条对应的insert记录,当update一条记录时,undo log它记录一条对应相反的update记录(即执行update之前什么样子的操作);当执行rollback时,就可以从undo log中的逻辑记录读取到相应的内容并进行回滚,这样就保证了事务的原子性。
Undo log销毁:undo log在事务执行时产生,事务提交时,并不会立即删除undo log,因为这些日志可能还用于MVCC(多版本并发控制)。
Undo log存储:undo log采用段的方式进行管理和记录,存放在前面介绍的 rollback segment回滚段中,内部包含1024个undo log segment。