由于近期工作涉及数据库相关的操作较多,就根据自己的实战经历整理了一些数据库开发的规范用法,利用 6 个“避免”来概括。
小伙伴们有兴趣想了解内容和更多相关学习资料的请点赞收藏+评论转发+关注我,后面会有很多干货。我有一些面试题、架构、设计类资料可以说是程序员面试必备!
所有资料都整理到网盘了,需要的话欢迎下载!私信我回复【111】即可免费获取
有句话叫做“别让脚趾头想事情,那是脑瓜子的职责”,用在数据库开发中,说的就是避免让数据库做她不擅长的事情。MySQL 并不擅长数学运算和逻辑判断,所以尽量不在数据库做运算,复杂运算可以移到程序端 CPU。
有次,有位同事让我看一条 SQL,说是在前台查询很快,但是把 SQL 取出来,在数据库中执行的时候,跑 10 分钟都不出结果。
看了一下 SQL,最后定位到一个视图中的一个子查询上面。该子查询的 SQL 文本如下:
SELECT acinv_07.id_item ,
SUM(acinv_07.dec_endqty) dec_endqty
FROM acinv_07
WHERE acinv_07.fiscal_year * 100 + acinv_07.fiscal_period
= ( SELECT DISTINCT
ctlm1101.fiscal_year * 100 + ctlm1101.fiscal_period
FROM ctlm1101 WHERE flag_curr = 'Y'
AND id_oprcode = 'acinv'
AND acinv_07.id_wh = ctlm1101.id_table)
GROUP BY acinv_07.id_item
复制代码
在 acinv_07 表上的列 fiscal_year 和列 fiscal_period 是有索引的。但是,如果对索引列进行运算,就会导致原本可以走索引的走不了索引。于是,动手改写成如下 SQL:
SELECT id_item ,
SUM(dec_qty) dec_qty
FROM dpurreq_03
GROUP BY id_item
) a ,
( SELECT a.id_item ,
SUM(a.dec_endqty) dec_endqty
FROM acinv_07 a ,
( SELECT DISTINCT
ctlm1101.fiscal_year ,
ctlm1101.fiscal_period ,
id_table
FROM ctlm1101
WHERE flag_curr = 'Y'
AND id_oprcode = 'acinv'
) b
WHERE a.fiscal_year = b.fiscal_year
AND a.fiscal_period = b.fiscal_period
AND a.id_wh = b.id_table
GROUP BY a.id_item
复制代码
再执行,4s 钟左右就可以跑出结果了。
总的来说,写 SQL 时,不到万不得已,不要对索引列进行计算。
在分页查询的时候,有的人总是习惯用 select count()获得总的记录条数,实际上这不是一个高效的做法,因为,之前获得数据的时候已经查询过一次了,select count()相当于同一个语句查询了两次,对数据库的开销自然就大了,我们应当使用数据库自带的 API,或者系统变量来完成这个工作。
大家在数据库表字段设计的时候,应该尽量都加上 NOT NULL DEFAULT ''。
使用 NULL 字段会产生很多不好的影响,例如:很难进行查询优化、NULL 列加索引,需要额外空间、含 NULL 复合索引无效……
看下面的案例:
数据初始化:
create table table1 (
`id` INT (11) NOT NULL,
`name` varchar(20) NOT NULL
)
create table table2 (
`id` INT (11) NOT NULL,
`name` varchar(20)
)
insert into table1 values (4,"zhaoyun"),(2,"zhangfei"),(3,"liubei")
insert into table2 values (1,"zhaoyun"),(2, null)
复制代码
(1) NOT IN 子查询在有 NULL 值的情况下返回永远为空结果,查询容易出错
select name from table1 where name not in (select name from table2 where id!=1)
复制代码
(2) 列值允许为空,索引不存储 null 值,结果集中不会包含这些记录。
select * from table2 where name != 'zhaoyun'
复制代码
select * from table2 where name != 'zhaoyun1'
复制代码
(3) 使用 concat 拼接时,首先要对各个字段进行非 null 判断,否则只要任何一个字段为空都会造成拼接的结果为 null
select concat("1", null) from dual;
复制代码
(4) 当计算 count 时候 null column 不会计入统计
select count(name) from table2;
复制代码
5、避免 select *
使用 select *可能会返回不使用的列的数据。它在 MySQL 数据库服务器和应用程序之间产生不必要的 I/O 磁盘和网络流量。
如果明确指定列,则结果集更可预测并且更易于管理。想象一下,当您使用 select *并且有人通过添加更多列来更改表格数据时,将会得到一个与预期不同的结果集。
使用 select *可能会将敏感信息暴露给未经授权的用户。
图片确实是可以存储到数据库里的,例如通过二进制流将图片存到数据库中。
但是,强烈不建议把图片存储到数据库中!!!!首先对数据库的读/写的速度永远都赶不上文件系统处理的速度,其次数据库备份变的巨大,越来越耗时间,最后对文件的访问需要穿越你的应用层和数据库层。
图片是数据库最大的杀手。一般来说数据库都是存储一个 URL,然后再通过 URL 来调用图片。
图片,文件,二进制数这三样东西慎重存储到数据库中。