当前位置: 首页 > 科技观察

美团专访:你在使用MySQL的过程中遇到过哪些坑?

时间:2023-03-18 13:45:00 科技观察

本文的技术面试题都是亲身体验过的。所以十年老手告诉你,作为后端开发,不管你公司有没有DBA,数据库相关的技术都是必备的。面试官:你对锁还是有把握的。菜鸟我:(微微一笑,表示回应)面试官:使用MySQL这么多年,有哪些让你难以忘怀的坑。菜鸟我:巴拉巴拉开始说了(面试前准备了这类面试题,泼水)下面,我根据自己的实战经验,整理了一些数据库开发的标准用法,用6个“回避”来总结.1.避免在数据库中进行计算。有句话叫“不要让你的脚趾头去想事情,那是你大脑的责任”。用在数据库开发中,意思是避免让数据库做她不擅长的事情。MySQL不擅长数学计算和逻辑判断,所以尽量不要在数据库中做计算,复杂的计算可以移到终端CPU上。2、避免对索引列进行操作。有同事让我看一个SQL,说在前台查询很快,但是把SQL拿出来在数据库中执行的时候,跑了10分钟就没有结果了。查看SQL后,我终于在视图中找到了一个子查询。该子查询的SQL文本如下:##以下SQL来源于网络SELECTacinv_07.id_item,SUM(acinv_07.dec_endqty)dec_endqtyFROMacinv_07WHEREacinv_07.fiscal_year*100+acinv_07.fiscal_period=(SELECTDISTINCTctlm1101.fiscal_year*100+ctlm1101.fiscal_periodFROMctlm1101WHEREflag_curr='Y'ANDid_oprcode='acinv'ANDacinv_07.id_wh=ctlm1101.id_table)表中GROUPBYacinv_07.id_item的列fiscal_year和列fiscal_period被索引acinv.07但是,如果对索引列进行操作,则会导致原来的索引无法使用。于是,动手改写成如下SQL:##以下SQL来源于网络SELECTid_item,SUM(dec_qty)dec_qtyFROMdpurreq_03GROUPBYid_item)a,(SELECTa.id_item,SUM(a.dec_endqty)dec_endqtyFROMacinv_07a,(SELECTDISTINCTctlm1101.fiscal_year,ctlm1101.fiscal_period,id_tableFROMctlm1101WHEREflag_curr='再次执行Y'ANDid_oprcode='acinv')bWHEREa.fiscal_year=b.fiscal_yearANDa.fiscal_period=b.fiscal_periodANDa.id_wh=b.id_tableGROUPBYa.id_item,4s左右就能运行出结果。一般写SQL的时候,除非绝对必要,否则不要计算索引列。3.避免使用count(*)在查询页面时,有些人总是习惯于使用selectcount()来获取总记录数,其实这不是一种高效的方法method.方法是因为数据之前查询过一次,selectcount()相当于查询了同一条语句两次,对数据库的开销自然很大,我们应该使用数据库自??带的API,或者系统变量4.设计时避免使用NULL字段数据库表字段,你应该尝试添加NOTNULLDEFAULT'。使用NULL字段会带来很多不好的影响,比如:难以进行查询优化,为NULL列添加索引需要额外的空间,包含NULL的复合索引无效……见如下案例:数据初始化:createtabletable1(`id`INT(11)NOTNULL,`name`varchar(20)NOTNULL)createtabletable2(`id`INT(11)NOTNULL,`name`varchar(20))insertintotable1values(4,"tianweichang"),(2,"zhangsan"),(3,"lisi")insertintotable2values(1,"tianweichang"),(2,null)(1)NOTIN子查询在有NULL值时返回的结果总是空,查询容易出错selectnamefromtable1wherenamenotin(selectnamefromtable2whereid!=1)(2)列值允许为空,索引不存储空值,这些记录不会被包含在结果集中。select*fromtable2wherename!='tianweichang'select*fromtable2wherename!='zhaoyun1'(3)使用concat拼接时,必须先对每个字段进行非空判断,否则只要有一个字段为空,拼接结果willbenullselectconcat("1",null)fromdual;(4)计算count时,name为null的不会被统计selectcount(name)fromtable2;5。避免select使用select*可能返回未使用列的数据。它会在MySQL数据库服务器和应用程序之间产生不必要的I/O磁盘和网络流量。如果显式指定列,则结果集更可预测且更易于管理。想象一下,当您使用select*并且有人通过添加更多列来更改表数据时,您将获得与预期不同的结果集。使用select*可能会将敏感信息暴露给未经授权的用户。6、避免将图片存入数据库图片确实可以存入数据库,比如通过二进制流将图片存入数据库。但是,强烈不建议将图片存入数据库!!!!首先,读取/写入数据库的速度永远赶不上文件系统的处理速度。其次,数据库备份变得庞大而且越来越耗时。最后,文件Access需要遍历你的应用层和数据库层。图像是数据库的最大杀手。一般来说,数据库存储一个URL,然后通过URL调用图片。图片、文件和二进制数都小心地存储在数据库中。