MySQL——SQL巩固&数据库优化&SQL优化

SQL巩固&数据库优化&SQL优化(待补充完整细节)

前言

对于初级程序开发工程师而言,SQL是很多人的弱项,为此我给大家来做一下总结,希望能够帮到你们。

课程说明

1、介绍项目实战开发过程中常用的MySQL函数及常用语法,并且分析三种联合查询原理及如何使用、什么时候使用;

2、针对数据库层面的优化方案做介绍说明;

3、对MySQL SQL优化方案做讲解,学习如何排查慢查询;

SQL巩固

初始化

说明:这里用大家熟知的电商业务来讲解,进一步巩固学习SQL

表结构创建

订单表

CREATE TABLE `tb_order` (
   `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '订单id',
   `user_id` int(11) NOT NULL COMMENT '用户id',
   `price` int(11) NOT NULL COMMENT '订单金额',
   `pay_time` datetime DEFAULT NULL COMMENT '支付时间',
   `create_time` datetime NOT NULL COMMENT '创建时间',
   `status` tinyint(4) NOT NULL DEFAULT '0' COMMENT '订单状态',
   `update_time` datetime DEFAULT NULL COMMENT '最后更新时间',
   PRIMARY KEY (`id`),
   KEY `IDX_USER_ID` (`user_id`),
   KEY `IDX_PAY_TIME` (`pay_time`),
   KEY `IDX_CREATE_TIME` (`create_time`)
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8 CHECKSUM=1 DELAY_KEY_WRITE=1 ROW_FORMAT=DYNAMIC COMMENT='订单表'

商品表

CREATE TABLE `tb_goods` (
   `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '商品id',
   `name` varchar(50) NOT NULL DEFAULT '' COMMENT '名称',
   `price` int(11) NOT NULL DEFAULT '0' COMMENT '单价',
   `stock` int(11) NOT NULL DEFAULT '0' COMMENT '库存',
   `status` smallint(6) NOT NULL DEFAULT '0' COMMENT '状态',
   PRIMARY KEY (`id`)
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8 CHECKSUM=1 DELAY_KEY_WRITE=1 ROW_FORMAT=DYNAMIC COMMENT='商品表'

由于一个订单可能包含多种商品,故存在

订单商品关系表

CREATE TABLE `tb_order_goods` (
   `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '关联数据id',
   `order_id` int(11) NOT NULL COMMENT '订单id',
   `goods_id` int(11) NOT NULL COMMENT '商品id',
   `goods_num` int(11) NOT NULL COMMENT '商品数量',
   `goods_price` int(11) NOT NULL COMMENT '商品单价',
   `sum_price` int(11) NOT NULL COMMENT '小计金额',
   PRIMARY KEY (`id`),
   KEY `IDX_ORDER_ID` (`order_id`),
   KEY `IDX_GOODS_ID` (`goods_id`)
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8 CHECKSUM=1 DELAY_KEY_WRITE=1 ROW_FORMAT=DYNAMIC COMMENT='商品订单关系表'

用户表

CREATE TABLE `tb_user` (
   `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '用户id',
   `name` varchar(32) DEFAULT NULL COMMENT '姓名',
   `phone` varchar(15) NOT NULL DEFAULT '' COMMENT '电话',
   `sex` varchar(1) DEFAULT NULL COMMENT '性别',
   `password` varchar(64) DEFAULT NULL COMMENT '密码',
   `user_name` varchar(18) NOT NULL COMMENT '用户名',
   `status` tinyint(3) DEFAULT NULL COMMENT '状态',
   PRIMARY KEY (`id`),
   KEY `IDX_PHONE` (`phone`),
   KEY `IDX_USER_NAME` (`user_name`)
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8 CHECKSUM=1 DELAY_KEY_WRITE=1 ROW_FORMAT=DYNAMIC COMMENT='用户表'

有的同学想要知道,针对已存在的表结构,如何添加索引呢?简单演示如下

给tb_user表name字段添加普通索引

-- IDX_NAME 为索引名,可自行定义
ALTER TABLE `tb_user` ADD INDEX `IDX_NAME` (`name`);

添加测试数据

INSERT  INTO `tb_goods`(`id`,`name`,`price`,`stock`,`status`) VALUES (1,'华为P30',600000,20,1),(2,'美特斯邦威男士夹克衫',29900,100,1);
INSERT  INTO `tb_order`(`id`,`user_id`,`price`,`pay_time`,`create_time`,`status`,`update_time`) VALUES (1,1,629900,'2020-02-01 00:00:00','2020-02-01 00:00:00',1,'2020-02-01 00:00:00'),(2,1,1200000,NULL,'2020-02-02 00:00:00',0,'2020-02-02 00:00:00'),(3,2,600000,'2020-03-01 00:00:00','2020-03-01 00:00:00',1,'2020-03-01 00:00:00');
INSERT  INTO `tb_order_goods`(`id`,`order_id`,`goods_id`,`goods_num`,`goods_price`,`sum_price`) VALUES (1,1,1,1,600000,600000),(2,1,2,1,29900,29900),(3,2,1,2,600000,1200000),(4,3,1,1,600000,600000);
INSERT  INTO `tb_user`(`id`,`name`,`phone`,`sex`,`password`,`user_name`,`status`) VALUES (1,'高M','18810531708','男','123456','gao_yue',1),(2,'明哥','18810532526','男','123654','tang_',1),(3,'培哥','15544455665','男','545466','pei_',1);

常见操作

count累计

count(值),这个值如果不是null则计1,值为null则计0

所以select count(1) from dual、select count(10000) from dual其结果都为1

而select count(null) from dual结果则为0

例如tb_user表中有三条数据,其中有一条数据的name字段为空,那么存在

1、select count(name) from tb_user结果则为2而非3,如果想要统计表中数据条数则用count(*)或count(id)

2、另外值得一说的是,select 1000 from tb_user表,其结果为3行1000,所以存在如下

3、select count(1000) from tb_user结果为3

count结合distinct使用可统计某个字段出现(除空值之外的)不同值的次数

比如查询订单表有多少笔金额相同的订单

select count(distinct(price)) from tb_order;

sum累加

sum(值),会把这个值的数值进行一个累加,sum(null)则为null

所以select sum(0) from dual结果为0,select sum(1000) from dual结果为1000

而select sum(null) from dual结果为null

故针对sum的字段如果可能出现null的话,需要提前做判断转换IFNULL(字段,代替值),避免出现统计错误

比如统计订单表订单销售总额(不区分订单状态)

select sum(ifnull(price,0)) from tb_order;

distinct去重

比如我们要查询所有下过单的用户id集合,这里结果集中针对相同id要做去重处理

SELECT DISTINCT user_id FROM tb_order;

group by、having、order by

在查询结果集之上再做查询

结果集行号、rownum

case when then else end

不用max、min如何找最大、最小

日期常见操作

now()
current_date、current_time
date_format()
unix_ timestamp
date_sub、date_add

字符串常见操作

concat
substr
left、right

if、男女性别互换

联合更新

查询结果集导入表

union、union all

联合查询

left join

right join

inner join、逗号连接

full join

这么多join方式如何选择

你应该知道的

联合索引按左匹配

数据库、表结构优化

优化的必要性

1、减轻关系型数据库访问压力,提升程序负载能力

2、加快响应速度,提升用户体验

3、慢查询引起的生产事故

4、表结构重构、数据迁移是巨大的工程

5、关系型数据库针对某些数据的存储不是那么合适

数据库表结构合理设计

数据库设计三范式

1、每一列是不可再分的属性值,同一列不能包含多个值,关系型数据库的特点之一

地址:省、市、区、具体地址

2、数据库表中每个实例或行必须可以被唯一地区分

需要有唯一能区分行数据的字段(主键)

3、一个数据表中不再包含已在其它表中包含的非主关键字信息(看情况)

订单数据,包含用户id,不再存储用户其它数据(看情况),(分布式系统中,比如下单时的用户手机号...)

设计符合业务的表结构

1、比如业务流程中,有明显的区分使用用户基础数据跟用户详情数据可以对应的建立用户基础表、用户详情表

2、多对多的关系设计中,使用中间关联表,如品牌表、分类表、品牌分类关联表

主从同步、读写分离

缓存

MySQL缓存

服务本地缓存

分布式缓存

分库分表

按业务垂直拆分

按数据水平拆分

NoSQL

NewSQL

存储引擎优化

数据归档

数据中台、数仓

SQL优化

分页查询优化

建立索引、使用索引

索引应建立在那些将用于JOIN、WHERE条件判断、ORDERBY排序的字段上

没有命中索引的SQL不允许执行

字段能小则小

索引不要建立在大字段上

索引建立在离散度大的字段上

批量插入

先导入数据再建立索引

某些情况下避免使用子查询

索引字段查询避免使用函数

禁止排序

group by ** order by null;

建立全文索引替换like模糊匹配

相同类型字段进行比较

减少锁的独占表的范围

如何排查慢查询

show [full] processlist

查看数据库各SQL执行进程情况

explain查看执行计划

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 219,869评论 6 508
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,716评论 3 396
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 166,223评论 0 357
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,047评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,089评论 6 395
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,839评论 1 308
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,516评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,410评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,920评论 1 319
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,052评论 3 340
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,179评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,868评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,522评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,070评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,186评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,487评论 3 375
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,162评论 2 356

推荐阅读更多精彩内容