前言我们出去面试的时候,经常会被问到数据库,而关于数据库问的最多的就是数据库优化。那么如何才能做好问题的优化呢?今天我们就来说说数据库优化。数据库优化一般可以从以下几个方面来考虑:数据库表设计sql语句优化数据库大型项目拆分成小项目,每个项目都有自己独立的数据库写请求也发送到这个MySQL,所以对数据库的负载是太高。如果将一个节点的数据库拆分成多个MySQL数据库,可以有效降低每个MySQL数据库的负载。表细分和数据库细分(模细分、水平细分、垂直细分)通过取模算法进行水平细分,比如一共有3张表,1%3=1放入第一张表,2%3=2.放在下面两张表,3%3=0放在第0张表,相当于用几张表平分一张表。最好的办法是一个主表,后面跟着几个词表。因为分表不容易做分页,数据存储在多个表中,所以需要一张主表来存储所有的数据,当分表不能满足要求时使用主表。读写分离,将数据库的读写操作划分到不同的数据库服务中,实现数据库的高性能、高并发;读写分离最大的缺点是复制延迟,更适合基于查询的项目。请参阅项目被折衷。表设计数据库表设计遵循三种范例。第一范式:原子约束,每一列都不能进一步划分第二范式:每张表只描述一个东西,即主键对应所有信息。第三范式:保证表中的数据与主键直接相关,而不是间接相关。比如订单表中出现了快递员的属性(快递单号、收件人姓名、收货地址),则可以将收件人姓名和收货地址单独放在一张表中,只留下快递单号订单表作为一个关联。并非所有的表格设计都必须按照这三种范式进行设计。具体需要根据需要确定。表字段设计尽量设计成notnull,尽量使用数值型字段(比如性别,男:1女:2),如果只有数值型的信息字段尽量不要设计成字符类型,会降低查询和连接的性能,增加存储开销。字段长度设计合理,比如邮政编码,只需要位长,没必要太长。使用varchar/nvarchar而不是char/nchar可以节省存储空间,因为变长字段的存储空间小,其次对于查询来说,在一个相对较小的字段中搜索效率明显更高。不要以为NULL不需要空间,例如:char(100)类型,在创建字段时,空间是固定的,无论是否插入值(也包括NULL),都会占用空间100个字符,如果是varchar这样的变长字段,null不占空间。SQL语句优化最大限度地利用索引,合理创建索引时,最大限度地利用索引减少数据访问:设置合理的字段类型返回更少的数据:只返回必填字段和数据分页处理减少交互次数:批量DML操作,函数存储等,减少数据连接数,尽量减少数据库排序操作,全表查询SQL语句优化。首先,我们需要定位是否存在慢查询。顾名思义,慢查询执行非常慢的查询。howslow超过long_query_time参数设置的时间阈值(默认10s)慢查询基本配置slow_query_log启停技术慢查询日志slow_query_log_file指定慢查询日志的存储路径和文件(默认与数据文件放在一起)long_query_time指定记录慢查询日志的SQL执行时间Defeat值(单位:秒,默认10秒)log_queries_not_using_indexes是否记录未使用索引的SQLlog_output日志存放的地方[TABLE][FILE][FILE,TABLE]Formysql5.7以上版本,在my.ini中配置慢查询Configuration#启动慢查询日志slow_query_log=ON#慢查询日志存放位置slow_query_log_file=D:\\software\\mysql\\mysql-5.7.24-winx64\\data\\logs\\show.log#设置慢查询时间,默认是10秒,我们这里设置为1秒,即超过1秒就是慢查询long_query_time=1通过下面的co查看上面的配置命令:显示变量如“%slow_query_log%”显示变量如“%slow_query_log_file%”显示变量如“%long_query_time%”显示变量如“%log_queries_not_using_indexes%”显示变量如“log_output”setgloballong_query_time=1;--默认10秒,这里设置为1setGLOBALslow_query_log=1;--启用慢查询日志setgloballog_output='FILE'--项目开发过程中,日志只能记录在日志文件中,不能记录在表中。比如我执行selectsleep(2)休眠两秒,超过了我设置的慢查询时间1秒,就会在慢查询日志中记录如下:查询时间和慢查询陈述。当我们知道了慢查询语句后,我们就可以有针对性地对sql进行优化。对SQL最优化的就是加索引,快速找到特定值的记录。MySQL的所有索引都以B树的形式存储。如果没有索引,MySQL在执行查询时必须从第一条记录开始扫描全表的所有记录,直到找到符合要求的记录。表中的记录数越大,此操作的成本就越高。如果在作为查找条件的列上建立了索引,MySQL可以在不扫描任何记录的情况下快速获取目标记录的位置。索引原理:对半搜索减少全表扫描,索引文件是一个B_tree,索引的最大搜索数为2^n次方,查找数独更快。我们可以使用explain来分析SQL的执行计划。执行计划可以模拟SQL优化器对SQL语句的执行,可以帮助我们了解索引对编写SQL是否有用。1)查看执行计划语法:explain+SQL语句eg:explainselect*fromtb;id:numberselect_type:querytypetable:tabletype:typepossible_keys:indexkeyusedinprediction:indexactuallyusedkey_len:indexactuallyusedlengthofref:表之间的引用rows:通过索引查询到的数据量Extra:创建索引的附加信息createindexindex_nameontable_name(colum_name...);索引使用注意事项常用字段加索引,主键除外,主键有自己的唯一索引。比如product表有很多name和price,就给这两个字段加索引,尽量避免使用子查询,使用关联查询代替selectt1.name,(selectsexfromuseru1whereu1.user_id=t1.user_id)assexfromuserInfot1toselectt1.name,u1.sexfromuserInfoleftjoinuseru1onu1.user_id=t1.user_id;用in代替or,并包含InQuery的范围,放在where条件的末尾,防止索引失效。select*fromep_productwherechannel_id=1orchannel_id=2改成select*fromep_productwherechannel_idin(1,2)尽量不要用or,否则索引失败。不要用like"%%",它会扫描全表,但是可以用like"_%",如果不是以%开头,会使用索引查找使用"%%"使用"_%”判断是否为null不能使用=,useisnull,=null不会使用索引,isnull会使用索引,避免数据类型不一致。如果设置了int类型,条件最好传入int类型。如果传入的是string类型,数据库会先进行转换再执行sqlselect*fromproductwhereid="1"select*fromproductwhereid=1数据库最好不要留NULL,填入数据库尽可能NOTNULL,可以给name设置一个默认值0,保证表中的name列没有空值,然后这样查询:selectidfromtwherename=0分组时需要更高效,禁止排序。addorderbynullselectchannel_id,count(*)fromep_productGROUPBYchannel_idtoselectchannel_id,count(*)fromep_productGROUPBYchannel_idorderbynull应该加在groupby之后尽量避免对where子句中的字段进行表达式操作,这将导致引擎放弃使用索引并执行全表扫描。select*fromproductwheresell_price/2=100改为select*fromproductwheresell_price=100*2使用索引字段作为条件时,如果索引是复合索引,则必须使用索引中的第一个字段as只有满足条件才能使用索引,否则不会使用索引,字段的顺序尽量和索引的顺序一致。复合索引,不要跨列或乱序使用(左匹配原则)复合索引,尽量使用全索引匹配,即如果创建多个索引,使用多个索引更新语句,如果只改变1或2个字段,不要更新所有字段,否则频繁调用会造成明显的性能消耗,同时带来大量的日志。select相应的效率,同时也降低了insert和update的效率,因为insert或者update都可能重建索引,所以如何建立索引需要慎重考虑,要看具体情况。其他注意事项避免select*关联查询的发生,最好不要超过3张表,数据库的性能更重要,最好适当考虑标准化。添加多条数据是为了避免使用insertintouservalues(1,"张三");insertintouservalues(2,"李四");使用以下方法减少语句解析insertintouservalues(1,"张三"),(2,"李四")的操作;总结以上就是小贝为大家总结的一些数据库优化思路。如有不妥之处,欢迎大家在评论区提出建议和补充。
