mysql学习笔记

基础操作

创建数据库

CREATE DATABASE db_name;

切换数据库

USE db_name;

创建表

CRETAE TABLE table_name(column type,...);

查看表结构

DESC table_name;

修改表名称

ALTER TABLES old_table_name RENAME TO new_table_name;

显示所有数据库

SHOW DATABASES;

显示所有表

SHOW TABLES;

修改数据库默认编码

ALTER DATABASE db_name DEFAULT CHARACTER SET encoding;

给表添加列

ALTER TABLE table_name ADD new_column type,…;

给表删除列

ALTER TABLE table_name DROP columnname;

插入数据

插入所有字段

INSERT INTO table_name VALUES(colum1, .....);

插入部分字段

INSERT table_name(colum1,..) VALUES(value1,...);

修改数据

UPDATE tableble_name SET columnname=value WHERE 条件;

删除全表

DELETE FROM table_name;
  • 可以带条件删除

  • 只能删除表的数据,不能删除表的约束

  • 可以回滚

    TRUNCATE TABLE table_name;

  • 不能带条件删除

  • 既可以删除表的数据,也可以删除表的约束

  • 不可以回滚

修改表

alter table TABLENAME

opt

修改字段类型

change old_field new_field new_type

添加字段

add field new_field type

添加字段并指定位置

add new_field new_type [完整性约束] [first | after 原有字段]

add [unique | fulltext | spatial] index index_name (field[len]) [asc | desc]

修改字段并指定位置

modify field type [完整性约束] [first | after 原有字段]

删除字段

drop field

删除外键

drop foreign key foreign_name

修改表明

rename new_table_name

视图

1create [algorithm = {undefined | merge | temptable}] 2 view view_name [{field...}] 3 as select 语句 4 [with [cascaded | local] check option];

查询

查询所有列

SELECT * FROM table_name;

查询指定列

SELECT column1,… FROM table_name;

查询时指定别名

SELECT column AS ‘column_new’,… FROM table_name AS table_name_new;

查询时添加常量列

SELECT column1,…’常量列’ FROM table_name;

查询时合并列

SELECT columname, (column1+column2) FROM table_name;
  • column1和column2必须为数值类型

查询时去除重复列

1SELECT DISTINCT column FROM table_name; 2SELECT DISTINCT(column) FROM table_name;
  • 条件查询(WHERE)

  • 逻辑条件:and(与) or(或)

    SELECT * FROM table_name WHERE column1=value AND column2=value SELECT * FROM table_name WHERE column1=value OR column2=value

  • 比较条件: > < >= <= <>(不等于) between and

    SELECT * FROM table_name WHERE column > value1 AND column < valu2; SELECT * FROM table_name WHERE column BETWEEN value1 AND value2;

  • 判空条件(null 空字符串) is null, is not null, =’’, <>’’

    SELECT column,… FROM table_name WHERE column is null;

  • 模糊条件(LIKE)

  • % 任意个字符

  • _ 一个字符

    SELECT * FROM table_name WHERE column LIKE “”

聚合查询

常用聚合函数

函数名

功能

SUM()

求和

AVG()

求平均值

MAX()

最大值

MIN()

最小值

COUNT()

计数

COUNT(*)

列数

COUNT(column)

行数

分页查询(LIMIT 起始行, 查询几行)

  • 起始行从0开始

  • 分页: 当前页 每页显示条数

  • 分页查询当前页的数据sql:SELECT * FROM table_name LIMIT (当前页-1)*每页显示条数,每页显示条数;

    SELECT * FROM table_name LIMIT start_line, count_line;

查询排序

SELECT * FROM table_name ORDER BY column ASC/DESC;

多列排序条件

SELECT * FROM table_name ORDER BY column1 ASC/DESC, column2 ASC/DESC;
  • 先按column1排序,对column1值相同的行,按column2排序

分组查询(GROUP BY)

SELECT column,COUNT(column/*) FROM table_name GROUP BY column;

分组查询后筛选

SELECT column,COUNT(column/*) FROM table_name GROUP BY column HAVING COUNT(column/*);

表约束

唯一:

  • unique:不可可重复,可以为空,一张表可以有多个

主键: 非空+unique

  • primary key:不可重复,不可为空,一张表只能有一个 自增长

    CREATE TABLE table_name(column type auto_inrement); CREATE TABLE table_name(column type zerofill auto_inrement);

  • 零填充不能影响自增长约束

    DELETE FROM table_name;

  • 可以影响自增长约束

    TRUNCATE TABLE table_name;

  • 外键约束

    CREATE TABLE table_name( column type, CONSTRAINT column_fk FOREIGN KEY(column) REFERENCES table_name_fk(column) 外键名称 外键 参考表 (参考字段));

  • 有外键约束时:

  1. 添加数据时:先添加主表(参考表),再添加副表
  2. 修改数据时:先修改副表,再修改主表(参考表)数据
  3. 删除数据时:先删除副表,再删除主表(参考表)数据
  • 级联操作
  1. 有外键约束时,通过修改或删除主表,影响副表

    CREATE TABLE table_name( column type, CONSTRAINT column_fk FOREIGN KEY(column) REFERENCES table_name_fk(column) ON UPDATE CASCADE[ ON DELETE CASCADE]); 外键名称 外键 参考表(参考字段)

    级联修改:ON UPDATE CASCADE 级联删除:ON DELETE CASCADE

数据库设计

需求分析

需求设计 概要设计 抽取实体:业务模型->实体模型(类) 数据库设计:业务模型/实体模型->数据模型()硬盘 详细设计 类详细,属性,方法 三大范式 设计原则:设计的表尽量遵守三大范式 第一范式:表中每个字段必须是不可分割的独立单元 第二范式:在第一范式的基础上,非主属性完全函数依赖于任何一个候选码 第三范式:在第二范式的基础上,非主属性既不传递依赖于码,也不函数依赖于码

MySQL存储过程

  • 执行效率快,在服务端执行
  • 移植性差

创建存储过程

1DELIMITER $ 声明结束符 2CREATE PROCEDURE proname() 3BEGIN 4SELECT * FROM table_name; 5... 6END $

执行存储过程

1CALL proname(); 2参数 3IN 输入参数,可以携带数据到存储过程中 4OUT 输出参数,可以从存储过程中返回结果 5INOUT 输入输出参数,既有输入功能,也有输出功能

带有存储输入参数的存储过程

1DELIMITER $ 2CREATE PROCEDURE proin(IN col type) 3BEGIN 4SELECT * FROM table_name WHERE column=col; 5END $ 6 7CALL proin(col);

带有输出参数的存储过程

1DELIMITER $ 2CREATE PROCEDURE proout(OUT col type) 3BEGIN 4 SET col = 'Hello MySQL!'; 5END $

删除存储过程

DROP PROCEDURE proout;

mysql变量

全局变量(内置变量)

SQL

意义

SHOW varibales

查看所有全局变量

select @@变量名

查看某个全局变量

set 变量名=新值

修改全局变量

character_set_client

mysql服务器的接收数据的编码

character_set_results

mysql服务器输出数据的编码

会话变量:只存在于当前客户端与数据库服务端的依次连接中,如果连接断开,那么会话变量全部丢失

SET @var='value';

局部变量:在存储过程中使用的变量

  1. 定义一个会话变量name
  2. 使用name会话变量接受存储过程的返回值

CALL proout(@name); SELECT @name;

带有输入输出参数的存储过程

1DELIMITER $ 2CREATE PROCEDURE proinout(INOUT var type) 3BEGIN 4SELECT var; 5SET var = value; 6END $ 7 8SET @var=value; 9CALL proinout(@var)

带有条件判断的存储过程

输入整数,返回对应星期天

1DELIMITER $ 2CREATE PROCEDURE proif(IN num INT, OUT str VARCHAR(20)) 3BEGIN 4IF num=1 THEN 5SET str='星期一'; 6IF num=2 THEN 7SET str='星期二'; 8IF num=3 THEN 9SET str='星期三'; 10ELSE 11SET str='输入错误'; 12END IF; 13END $ 14 15CALL proif(1,@str); 16 17SELECT @str;

带有循环功能的存储过程

输入数值,求从一到该数值的累加和

1DELIMITER $ 2CREATE PROCEDURE prowhile(IN num INT, OUT result INT) 3BEGIN 4// 定义一个局部变量 5DECLARE i INT DEFAULT 1; 6DECLARE vsum INT DEFAULT 0; 7WHILE i<=num DO 8SET vsum=vsum+i; 9SET i=i+1; 10END WHILE; 11SET result=vsum; 12END $ 13 14CALL prowhile(122, @result) 15 16SELECT @result;

MySQL触发器

当操作某张表时,同时触发一些动作 插入数据后,同时向日志表中插入

  • 创建触发器(插入)

    CREATE TRIGGER triname AFTER INSERT ON table_name FOR EACH ROW INSERT INTO log_table_name(clomn,...) VALUES('INSERT');

  • 创建触发器(修改)

    CREATE TRIGGER triname AFTER UPDATE ON table_name FOR EACH ROW INSERT INTO log_table_name(clomn,...) VALUES('update');

  • 创建触发器(删除)

    CREATE TRIGGER triname AFTER DELETEON table_name FOR EACH ROW INSERT INTO log_table_name(clomn,...) VALUES('delete');

mysql权限

修改密码

UPDATE USER SET PASSWORD=PASSWORD('new_passwd') WHERE USERN='USErname';

分配权限

1GRANT SELECT ON DATABASE.table TO 'USEr'@'accounttype' IDENTIFIED BY 'password'; 2GRANT DELETE ON DATABASE.table TO 'USEr'@'accounttype' IDENTIFIED BY 'password';

mysql备份和还原

不需要登录

1MYSQLDUMP -u USErname -p DATABASE > path 2MYSQL -u USErname -p DATABASE < path
  • 复制表

    CREATE TABLE table_name LIKE tablename;

事务

查询正在执行的事务(kill事务的线程ID(trx_mysql_thread_id))

1SELECT 2 * 3FROM 4 information_schema.INNODB_TRX;

查看正在锁的事务

1SELECT 2 * 3FROM 4 INFORMATION_SCHEMA.INNODB_LOCKS;

查看等待锁的事务

1SELECT 2 * 3FROM 4 INFORMATION_SCHEMA.INNODB_LOCK_WAITS;

查看事务等待状况

1SELECT 2 r.trx_id waiting_trx_id, 3 r.trx_mysql_thread_id waiting_thread, 4 r.trx_query waiting_query, 5 b.trx_id blocking_trx_id, 6 b.trx_mysql_thread_id blocking_thread, 7 b.trx_query blocking_query 8FROM 9 information_schema.innodb_lock_waits w 10 INNER JOIN information_schema.innodb_trx b ON b.trx_id = w.blocking_trx_id 11 INNER JOIN information_schema.innodb_trx r ON r.trx_id = w.requesting_trx_id;

查看更具体的事务等待状况

1SELECT 2 b.trx_state, 3 e.state, 4 e.time, 5 d.state AS block_state, 6 d.time AS block_time, 7 a.requesting_trx_id, 8 a.requested_lock_id, 9 b.trx_query, 10 b.trx_mysql_thread_id, 11 a.blocking_trx_id, 12 a.blocking_lock_id, 13 c.trx_query AS block_trx_query, 14 c.trx_mysql_thread_id AS block_trx_mysql_tread_id 15FROM 16 information_schema.innodb_lock_waits a 17 LEFT JOIN information_schema.innodb_trx b ON a.requesting_trx_id = b.trx_id 18 LEFT JOIN information_schema.innodb_trx c ON a.blocking_trx_id = c.trx_id 19 LEFT JOIN information_schema.PROCESSLIST d ON c.trx_mysql_thread_id = d.id 20 LEFT JOIN information_schema.PROCESSLIST e ON b.trx_mysql_thread_id = e.id 21ORDER BY 22 a.requesting_trx_id;

查看未关闭的事务

1SELECT 2 a.trx_id, 3 a.trx_state, 4 a.trx_started, 5 a.trx_query, 6 b.id, 7 b.USER, 8 b.HOST, 9 b.db, 10 b.command, 11 b.time, 12 b.state, 13 b.info 14FROM 15 information_schema.innodb_trx a 16 LEFT JOIN information_schema.PROCESSLIST b ON a.trx_mysql_thread_id = b.id 17WHERE 18 b.command = 'sleep';

未关闭事务信息

1SELECT 2 t1.trx_id, 3 t1.trx_started, 4 t1.trx_mysql_thread_id, 5 t3.event_id, 6 t3.end_event_id, 7 t3.sql_text, 8 concat( 'mysql --login-path=3306 -e ''kill', t1.trx_mysql_thread_id, '''' ) 9FROM 10 information_schema.innodb_trx t1 11 LEFT JOIN `performance_schema`.threads t2 ON t1.trx_mysql_thread_id = t2.processlist_idleft 12 JOIN `performance_schema`.events_statements_history t3 ON t2.thread_id = t3.thread_id 13WHERE 14 t1.trx_started < date_sub( now(), INTERVAL 1 MINUTE ) 15 AND t1.trx_operation_state IS NULL 16 AND t1.trx_query IS NULL 17ORDER BY 18 event_id DESC;

查看某段时间以来未关闭事务

1SELECT 2 trx_id, 3 trx_started, 4 trx_mysql_thread_id 5FROM 6 information_schema.innodb_trx 7WHERE 8 trx_started < date_sub( now(), INTERVAL 1 MINUTE ) 9 AND trx_operation_state IS NULL 10 AND trx_query IS NULL;

SQL优化

使用union all替代or

1select id from t where num=10 or num=20; 2select id from t where num=10 3union all 4select id from t where num=20;

查询优化器

  • 根据条件找到所有可能使用的索引
  • 计算全表扫描的代价
  • 计算使用不同索引的代价
  • 对比各种执行方案,找出成本最低的一个

慎用in和not in

1select id from t1 where num in (select id from t2 where id > 10); 2select id from t1, (select id from t1 where id > 10) t2 where t1.id=t2.id;

将字段函数计算放在等号右边

使用符合索引的第一个字段作为查询条件

使用exists替代in

1select num from a where num in (select num from b); 2select num from a where exists (select 1 from b where num=a.num);

多使用数字类型字段

全局锁

flush tables with read lock(FTWRL) set global readonly=true

表级锁

表锁

lock tables xxx read/writ // 加锁 unlock tables xxx read/writ // 释放锁

元数据锁MDL(metadata lock)

  • 进行增删改查时自动加上,保证数据读写正确性
  • 读写锁之间互斥,保证表结构变更的正确性

行级锁

  • 在需要的时候加上,事务结束后释放

帮助

?CONTENTS

MySQL索引

查看索引

SHOW INDEX FROM table_name;

创建索引

1ALTER TABLE table_name ADD INDEX index_name(column_list); 2CREATE INDEX index_name ON table_name(column_list);

创建唯一索引

1ALTER TABLE table_name ADD UNIQUE(column_list); 2CREATE UNIQUE INDEX index_name ON table_name(column_list);

创建主键索引

ALTER TABLE table_name ADD PRIMARY KEY(column_list);

删除索引

1ALTER TABLE table_name DROP INDEX index_name; 2DROP INDEX index_name ON table_name;

删除主键

ALTER TABLE table_name DROP PRIMARY KEY;

MySQL视图

  • 创建视图

    CREATE VIEW view_name AS SELECT * FROME table_name WHERE ....;

  • 删除视图

    DROP VIEW view_name;

  • 修改视图

    ALTER VIEW view_name;

MySQL内置函数

字符串函数

功能

函数名

连接

CONCAT(string[,...])

转小写

LCASE(string)

转大写

UCASE(string)

长度

LENGTH(string)

去除左端空格

LTRIM(string)

去除右端空格

RTRIM(string)

重复count次

REPEAT(string, count)

替换

REPLACE(str, search_str, replace_str)

从position开始,截取length个字符

SUBSTRING(str, position[,length])

生成count个空格

SPACE(count)

数学函数

功能

函数名

十进制转二进制

BIN(decimal_number)

向上取正

CEILING(number)

向下取正

FLOOR(number)

取最大值

MAX(num1, num2)

取最小值

MIN(num1, num2)

开平方

SQRT(number)

返回0-1内的随机值

RAND()

日期函数

功能

函数名

返回当前日期

CURDATE()

返回当前时间

CURTIME()

返回当前日期时间

NOW()

返回当前date的UNIX时间戳

UNIX_TIMESTAMP(date)

返回UNIX时间戳日期值

FROM_UNIXTIME()

返回date为一年中的第几周

WEEK(date)

返回date的年份

YEAR(date)

返回expr和expr2之间的天数

DATEDIFF(expr, expr2)

MySQL预处理

  • 设置预处理

    PREPARE pre_name FROM 'SELECT ... FROM table_name WHERE ?';

  • 设置变量

    SET @var=value;

  • 执行预处理

    EXECUTE pre_name using @var;

  • 删除预处理

    DROP PREPARE pre_name;

MySQL事务处理(MyISAM引擎不支持)

功能

语句

关闭自动提交功能

SET AUTOCOMMIT=0;

创建还原点

SAVEPOINT p_name;

回滚还原点

ROLLBACK TO p_name;

回滚所有

ROLLBACK;

  • 重排AUTO_INCREMENT值 清空表时用

    TRUNCATE TABLE table_name; ALTER TABLE table_name AUTO_INCREMENT=1;

  • 正则表达式

    SELECT * FROM * WHERE col REGEXP "recp";

  • 提取随机行

    SELECT * FROM table_name ORDER BY RAND();

  • 统计更多信息

    SELECT * FROM table_name GROUP BY ... WITH ROLLUP;

  • 数值之间逻辑位运算

    SELECT col0, BIT_OR(col1) FROM table_name GROUP BY col0; SELECT col0, BIT_AND(col1) FROM table_name GROUP BY col0;

  • MyISAM引擎不支持外键

优化SQL语句

  • 各种SQL执行频率

    SHOW [SESSION|GLOBAL] STATUS; SESSION (默认) 当前连接 GLOBAL 自数据库启动

  • Com_XXX表示XXX语句执行次数

字段名

意义

Com_select

一次查询只累计加1

Com_update

执行update次数

Com_insert

批量插入只算一次

Com_delete

执行delete次数

  • 只针对InnoDB存储引擎

字段名

意义

Innodb_rows_read

执行select操作次数

Innodb_rows_updated

执行update操作次数

Innodb_rows_inserted

执行insert操作次数

Innodb_rows_deleted

执行delete操作次数

字段名

意义

CONNECTIONS

连接MySQL的次数

Uptime

数据库已运行的时间(秒)

Slow_queries

慢查询的次数

  • 定位执行效率较低的SQL语句

    EXPLAIN SELECT * FROM table_name WHERE ...; DESC SELECT * FROM table_name WHERE ...;

MySQL优化

索引优化

  • MyISAM独立表空间
  • InnoDB共享表空间

使用索引

  • 查询条件中用到复合索引的第一列
  • 列名是索引, 使用column_name IS NULL 将使用索引
  • 使用LIKE的查询, 使用常量并且只有%号不在第一个字符, 索引才可能被使用
  • 对大的文本进行搜索, 使用全文索引而不使用LIKE'%...%'

不使用索引

  • MySQL估计使用索引比全表扫描更慢, 则不使用索引
  • 使用MEMORY/HEAP表并且WHERE条件中不使用'=', 则不会使用索引
  • 用OR分割的条件中, 前面列有索引, 后面列没有索引, 则不使用索引
  • WHERE子句的条件中, 用到的列不是复合索引的第一列
  • 使用LIKE的查询, 使用常量并且只有%号在第一个字符
  • 把数值型常量赋值给一个字符串型的列, 即使字符串型的列上有索引, 也不会用到

查看索引使用情况

1SHOW STATUS LIKE 'Handler_read%'; 2Handler_read_first 16
  • 一行被索引值读的次数

Handler_read_key 1079 Handler_read_last 0

  • 值越高 查询运行效率越低

Handler_read_next 152 Handler_read_prev 0 Handler_read_rnd 130 Handler_read_rnd_next 4166

分析表(检查表是否有错误)

CHECK TABLE table_name[, table_name]...[option] = {QUICK|FAST|MEDIUM|EXTENDED|CHANGED}

优化表

OPTIMIZE[LOCAL|NO_WRITE_TO_BINLOG] TABLE table_name[, table_name]

批量导入大量数据

LOAD DATA INFILE 'file_name' INTO TABLE table_name;

批量导出大量数据

SELECT ... FROM table_name INTO OUTFILE 'file_name'

提高导入效率

  • 将导入数据按主键顺序排列

  • 关闭唯一性检验(必须保证唯一键唯一)

    set unique_checks=0

  • 关闭自动提交

    set autocommit=0

优化INSERT语句

  • 尽量插入多个值(减少频繁INSERT对数据库连接,关闭等的损耗)
  • 使用INSERT DELAYED(马上执行)

优化GROUP BY 语句

  • 查询包含GROUP BY但不需要排序, 使用ORDER BY NULL来禁止排序

优化嵌套查询(使用JOIN)

表优化

  • 对常用列建索引

数据库优化

  • 分库分表
  • 分区

MySQL优化(MYISAM)

读锁 写锁

MySQL服务器优化

四种字符集

binary log日志

slow log慢查询日志 log_slow_queries=slow.log long_query_time=5

查询优化

1、使用慢查询日志,找出执行慢的查询。 关于Mysql 数据库查询优化的24条优化建议 2、使用 EXPLAIN 来决定查询功能是否合适。 3、经常测试你的查询,看是否需要做性能优化 性能可能会随着时间的变化而变化。 4、避免在整个表上使用count(*) ,它可能会将整个表锁住。 5、保持查询一致,这样后续类似的查询就能使用查询缓存了。 6、如果合适,用 GROUP BY 代替 DISTINCT。 7、在 WHERE、GROUP BY 和 ORDER BY 的列上加上索引。 8、保证索引简单,不要在同一列上加多个索引。 9、有时,MySQL 会选择错误的索引,这种情况使用 USE INDEX。 关于Mysql 数据库查询优化的24条优化建议 10、使用 SQL_MODE=STRICT 来检查问题。 11、索引字段少于5个时,UNION 操作用 LIMIT,而不是 OR。 12、使用 INSERT ON DUPLICATE KEY 或 INSERT IGNORE 来代替 UPDATE,避免 UPDATE 前需要先 SELECT。 13、使用索引字段和 ORDER BY 来代替 MAX。 14、避免使用 ORDER BY RAND()。 15、LIMIT M,N 在特定场景下会降低查询效率,有节制使用。 16、使用 UNION 来代替 WHERE 子句中的子查询。 17、对 UPDATE 来说,使用 SHARE MODE 来防止排他锁。 18、重启 MySQL 时,记得预热数据库,确保将数据加载到内存,提高查询效率。 19、使用 DROP TABLE ,然后再 CREATE TABLE ,而不是 DELETE FROM ,以删除表中所有数据。 20、最小化你要查询的数据,只获取你需要的数据,通常来说不要使用 *。 21、考虑持久连接,而不是多次建立连接,已减少资源的消耗。 22、基准查询,包括服务器的负载,有时一个简单的查询会影响其他的查询。 23、当服务器的负载增加时,使用SHOW PROCESSLIST来查看慢的/有问题的查询。 24、在存有生产环境数据副本的开发环境中,测试所有可疑的查询

1乐观锁-++ ++-表锁 2 | | 3 | | 4 |+加锁机制+---+ +---+锁粒度++-页锁 5 | | | | 6 | | | | 7悲观锁-++ |======| ++-行锁 8 || 9 |======| 10共享锁-++ | | ++-记录锁 11 | | | ++-gap锁 12 |+加锁机制+---+ +---+锁模式++-next-key锁 13 | ++-意向锁 14排它锁-++ ++-插入意向锁

幻读

一次事务中,多次查询的结果集不一致

快照读

普通select * from xx where xx;属于快照读

将历史数据存一份快照,从快照中读

当前读(next-key锁)

  • 记录锁(行锁),加在索引上

  • 间隙锁

    select * from xx where xx for update; select * from xx where xx lock in share mode; insert update delete

MVCC

write UPDATE和DELETE

  • 每个write操作使对象产生新的版本
  • 每个并发read操作依赖于隔离级别读取不同的版本

锁监控

  • 15s输出一次
  • 服务重启后自动复位

标准监控

判断是否存在名为innodb_monitor的数据表,来开启标准监控

1create table innodb_monitor (a int) engin=innodb; 2drop table innodb_monitor; 3 4 5set global innodb_status_output=on; 6set global innodb_status_output=off;

锁监控

1create table innodb_lock_monitor (a int) engin=innodb; 2drop table innodb_lock_monitor; 3 4 5set global innodb_status_output=on; 6set global innodb_status_output_locks=on; 7set global innodb_status_output_locks=off;

表空间监控

1create table innodb_tablespace_monitor (a int) engin=innodb; 2drop table innodb_tablespace_monitor;

表监控

1create table innodb_table_monitor (a int) engin=innodb; 2drop table innodb_table_monitor;

规范

一、基础规范

  • 表存储引擎必须使用InnoDB

  • 表字符集默认使用utf8,必要时候使用utf8mb4 解读: (1)通用,无乱码风险,汉字3字节,英文1字节 (2)utf8mb4是utf8的超集,有存储4字节例如表情符号时,使用它

  • 禁止使用存储过程,视图,触发器,Event 解读: (1)对数据库性能影响较大,互联网业务,能让站点层和服务层干的事情,不要交到数据库层 (2)调试,排错,迁移都比较困难,扩展性较差

  • 禁止在数据库中存储大文件,例如照片,可以将大文件存储在对象存储系统,数据库中存储路径

  • 禁止在线上环境做数据库压力测试

  • 测试,开发,线上数据库环境必须隔离

二、命名规范

  • 库名,表名,列名必须用小写,采用下划线分隔

解读:abc,Abc,ABC都是给自己埋坑

  • 库名,表名,列名必须见名知义,长度不要超过32字符 解读:tmp,wushan谁TM知道这些库是干嘛的

  • 库备份必须以bak为前缀,以日期为后缀

  • 从库必须以-s为后缀

  • 备库必须以-ss为后缀

三、表设计规范

  • 单实例表个数必须控制在2000个以内

  • 单表分表个数必须控制在1024个以内

  • 表必须有主键,推荐使用UNSIGNED整数为主键

  • 潜在坑:删除无主键的表,如果是row模式的主从架构,从库会挂住

  • 禁止使用外键,如果要保证完整性,应由应用程式实现 解读:外键使得表之间相互耦合,影响update/delete等SQL性能,有可能造成死锁,高并发情况下容易成为数据库瓶颈

  • 建议将大字段,访问频度低的字段拆分到单独的表中存储,分离冷热数据 解读:具体参加《如何实施数据库垂直拆分》

四、列设计规范

  • 根据业务区分使用tinyint/int/bigint,分别会占用1/4/8字节

  • 根据业务区分使用char/varchar 解读: (1)字段长度固定,或者长度近似的业务场景,适合使用char,能够减少碎片,查询性能高 (2)字段长度相差较大,或者更新较少的业务场景,适合使用varchar,能够减少空间

  • 根据业务区分使用datetime/timestamp 解读:前者占用5个字节,后者占用4个字节,存储年使用YEAR,存储日期使用DATE,存储时间使用datetime

  • 必须把字段定义为NOT NULL并设默认值 解读: (1)NULL的列使用索引,索引统计,值都更加复杂,MySQL更难优化 (2)NULL需要更多的存储空间 (3)NULL只能采用IS NULL或者IS NOT NULL,而在=/!=/in/not in时有大坑

  • 使用INT UNSIGNED存储IPv4,不要用char(15)

  • 使用varchar(20)存储手机号,不要使用整数 解读: (1)牵扯到国家代号,可能出现+/-/()等字符,例如+86 (2)手机号不会用来做数学运算 (3)varchar可以模糊查询,例如like ‘138%’

  • 使用TINYINT来代替ENUM 解读:ENUM增加新值要进行DDL操作

五、索引规范

  • 唯一索引使用uniq_[字段名]来命名

  • 非唯一索引使用idx_[字段名]来命名

  • 单张表索引数量建议控制在5个以内 解读: (1)互联网高并发业务,太多索引会影响写性能 (2)生成执行计划时,如果索引太多,会降低性能,并可能导致MySQL选择不到最优索引 (3)异常复杂的查询需求,可以选择ES等更为适合的方式存储

  • 组合索引字段数不建议超过5个 解读:如果5个字段还不能极大缩小row范围,八成是设计有问题

  • 不建议在频繁更新的字段上建立索引

  • 非必要不要进行JOIN查询,如果要进行JOIN查询,被JOIN的字段必须类型相同,并建立索引 解读:踩过因为JOIN字段类型不一致,而导致全表扫描的坑么?

  • 理解组合索引最左前缀原则,避免重复建设索引,如果建立了(a,b,c),相当于建立了(a), (a,b), (a,b,c)

六、SQL规范

  • 禁止使用select *,只获取必要字段 解读: (1)select *会增加cpu/io/内存/带宽的消耗 (2)指定字段能有效利用索引覆盖 (3)指定字段查询,在表结构变更时,能保证对应用程序无影响

  • insert必须指定字段,禁止使用insert into T values() 解读:指定字段插入,在表结构变更时,能保证对应用程序无影响

  • 隐式类型转换会使索引失效,导致全表扫描

  • 禁止在where条件列使用函数或者表达式 解读:导致不能命中索引,全表扫描

  • 禁止负向查询以及%开头的模糊查询 解读:导致不能命中索引,全表扫描

  • 禁止大表JOIN和子查询

  • 同一个字段上的OR必须改写问IN,IN的值必须少于50个

  • 应用程序必须捕获SQL异常 解读:方便定位线上问题

MySQL脚本

碎片整理-存储过程

1DELIMITER $$ 2DROP PROCEDURE 3IF 4 EXISTS `mysql`.`sp_optimize_tables2` $$ CREATE PROCEDURE `mysql`.`sp_optimize_tables2` ( 5 IN db_name VARCHAR ( 255 )) BEGIN-- To optimize all the tables in exact database. 6 DECLARE 7 cnt INT DEFAULT 0; 8 DECLARE 9 i INT DEFAULT 0; 10 SELECT 11 count(*) AS total 12 FROM 13 information_schema.TABLES 14 WHERE 15 table_schema = db_name INTO cnt; 16 WHILE 17 i < cnt DO-- Get the table's exact name. 18 19 SET @stmt = concat( 'select table_name from information_schema.tables where table_schema = ''', db_name, ''' order by table_name asc limit ', i, ',1 into @tb_name' ); 20 PREPARE s1 21 FROM 22 @stmt; 23 EXECUTE s1; 24 DROP PREPARE s1; 25 26 SET @stmt = ''; 27 28 SET @stmt = concat( 'alter table ', db_name, '.', @tb_name, ' engine=innodb' ); 29 PREPARE s1 30 FROM 31 @stmt; 32 EXECUTE s1; 33 DROP PREPARE s1; 34 35 SET @stmt = ''; 36 37 SET i = i + 1; 38 39 END WHILE;-- Refresh tables. 40 FLUSH TABLES; 41 42END $$DELIMITER;
点赞
收藏

评论区

加载中...

相关推荐

MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1

文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s

Oracle 分组与拼接字符串同时使用

SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(

MySQL部分从库上面因为大量的临时表tmp_table造成慢查询

背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_

皕杰报表之UUID

​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为

手写Java HashMap源码

HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22

2020年前端实用代码段,为你的工作保驾护航

有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )

mysql学习笔记 - HelloWorld