当前位置: 首页 > 后端技术 > Java

SQL优化的一些建议,希望能对像我一样被SQL折磨的你有所帮助

时间:2023-04-01 20:01:50 Java

6.1优化insert语句在进行数据插入操作时,可以考虑以下优化方案。如果需要同时向一张表中插入多行数据,应尽量使用多值表的insert语句。这种方式会大大减少客户端与数据库之间的连接和关闭。使效率比单独执行单个插入语句更快。示例,原始方法为:insertintoxxxvalues(1,'Tom');insertintoxxxvalues(2,'Cat');insertintoxxxvalues(3,'Jerry');优化后的方案为:insertintoxxxvalues(1,'Tom'),(2,'Cat'),(3,'Jerry');数据有顺序插入insertintotb_testvalues(4,'Tim');insertintotb_testvalues(1,'Tom');insertintotb_testvalues(3,'Jerry');insertintotb_testvalues(5,'Rose');insertintotb_testvalues(2,'Cat');优化后insertintotb_testvalues(1,'Tom');插入tb_test值(2,'Cat');插入tb_test值(3,'Jerry');插入tb_test值(4,'Tim');插入tb_test值(5,'Rose');6.2优化orderby语句6.2.1环境准备CREATETABLE`emp`(`id`int(11)NOTNULLAUTO_INCREMENT,`name`varchar(100)NOTNULL,`age`int(3)NOTNULL,`salary`int(11)NOTNULL,PRIMARYKEY(`id`))ENGINE=InnoDBDEFAULTCHARSET=utf8;insertinto`emp`(`id`,`name`,`age`,`salary`)values('1','Tom','25','2300');插入`emp`(`id`,`name`,`age`,`salary`)values('2','Jerry','30','3500');插入`emp`(`id`,`name`,`age`,`salary`)values('3','Luci','25','2800');插入`emp`(`id`,`name`,`age`,`salary`)值('4','杰伊','36','3500');插入`emp`(`id`,`name`,`age`,`salary`)values('5','Tom2','21','2200');插入`emp`(`id`,`name`,`age`,`salary`)values('6','Jerry2','31','3300');插入`emp`(`id`,`name`,`age`,`salary`)values('7','Luci2','26','2700');插入`emp`(`id`,`name`,`age`,`salary`)values('8','Jay2','33','3500');插入`emp`(`id`,`name`,`age`,`salary`)values('9','Tom3','23','2400');插入`emp`(`id`,`name`,`age`,`salary`)values('10','Jerry3','32','3100');插入`emp`(`id`,`name`,`age`,`salary`)values('11','Luci3','26','2900');insertinto`emp`(`id`,`name`,`age`,`salary`)values('12','Jay3','37','4500');在emp(age,salary)上创建索引idx_emp_age_salary);6.2.2两种排序方法1)。首先是对返回的数据进行排序,也就是俗称的filesort排序技巧。FileSort排序解释select*fromemporderbyagedesc;解释select*fromemporderbyageasc;2).第二种通过有序索引顺序扫描直接返回有序数据,利用索引,不需要额外排序,运行效率高。explainselectidfromemporderbyageasc;explainselectid,agefromemporderbyageasc;explainselectid,age,salaryfromemporderbyageasc;multi-fieldsorting--多字段排序explainselectid,年龄、薪水来自emp按年龄、薪水排序;解释selectid,age,salaryfromemporderbyagedesc,salarydesc;解释selectid,age,salaryfromemporderbysalarydesc,agedesc;explainselectid,age,salaryfromemporderbyagedesc,salaryasc;总结:了解了MySQL的排序方式后,优化目标很明确:尽量减少额外排序,直接通过索引返回排序后的数据。where条件和Orderby使用同一个索引,OrderBy的顺序和索引顺序一样,Orderby的字段都是升序或者降序。否则肯定需要额外的操作,所以才会出现FileSort。6.2.3Filesort的优化原理tips如果知道的话,可以通过创建合适的索引来减少Filesort的出现,但是在某些情况下,条件约束并不能使Filesort消失,所以需要加快排序操作的速度文件排序。对于Filesort,MySQL有两种排序算法:1)二次扫描算法:在MySQL4.1之前,采用这种方式进行排序。首先根据条件取出排序字段和行指针信息,然后在排序区的排序缓冲区中进行排序。如果排序缓冲区不够,则将排序结果存入临时表。排序完成后,根据行指针将记录读回表中,可能会引起大量的随机I/O操作。2)一次性扫描算法:一次性取出所有满足条件的字段,然后在排序缓冲区中排序后直接输出结果集。排序的内存开销较大,但排序效率高于二次扫描算法。MySQL通过比较系统变量max_length_for_sort_data的大小与Query语句提取的字段的总大小来确定使用哪种排序算法。如果max_length_for_sort_data较大,则使用第二种优化算法;否则,使用第一个。可以适当增加sort_buffer_size和max_length_for_sort_data系统变量来增加排序区域的大小,提高排序效率。显示像“max_length_for_sort_data”这样的变量;显示像“sort_buffer_size”这样的变量;6.3groupby语句优化tips继续使用6.2orderby语句优化创建索引的emp表(准备工作):createindexidx_emp_age_salaryonemp(age,salary);因为GROUPBY其实也进行了排序操作,而与ORDERBY相比,GROUPBY主要只是在排序后增加了分组操作。当然如果在分组的时候使用了一些其他的聚合函数,那么也需要进行一些聚合函数的计算。因此,在GROUPBY的实现过程中,也可以像ORDERBY一样使用索引。如果查询中包含groupby,但用户又想避免排序后的结果被消费,可以执行orderbynull来关闭排序。如下:dropindexidx_emp_age_salaryonemp;解释selectage,count(*)fromempgroupbyage;优化后解释selectage,count(*)fromempgroupbyageorderbynull;从上面的例子可以看出,第一条SQL语句需要进行“filesorted”,而第二条SQL因为orderbynull所以不需要进行“filesorted”,而且如前所述,Filesort往往很time-消费。6.4嵌套查询优化技巧继续使用4.3中创建的表使用explain分析执行计划Mysql4.1开始支持SQL子查询。该技术使用SELECT语句创建单列查询结果,然后将此结果用作另一个查询中的过滤条件。使用子查询可以一次完成很多逻辑上需要多步才能完成的SQL操作,还可以避免事务或表锁,而且编写简单。然而,在某些情况下,子查询可以被更高效的连接(JOIN)所取代。查找所有具有角色的用户信息的示例:explainselect*fromt_userwhereidin(selectuser_idfromuser_role);执行计划为:优化后:explainselect*fromt_useru,user_roleurwhereu.id=ur.user_id;Join查询效率更高的原因是MySQL不需要在内存中创建临时表来完成这个查询在逻辑上需要两个步骤。6.5使用技巧SQL技巧:继续使用5.2.1准备环境中创建的表SQL技巧,这是优化数据库的重要手段。简单的说,就是在SQL语句中加入一些人为的提示,以达到优化操作的目的。6.5.1USEINDEX在查询语句的表名后加上useindex,提供一个你希望MySQL引用的索引列表,这样MySQL就不再考虑其他可用的索引。在tb_seller(name)上创建索引idx_seller_name;explainselect*fromtb_sellerwherename='小米科技'explainselect*fromtb_selleruseindex(idx_seller_name)wherename='小米科技'6.5.2IGNOREINDEX如果用户只是想让MySQL忽略一个或多个索引,可以使用忽略索引作为提示。解释select*fromtb_sellerignoreindex(idx_seller_name_sta_addr)wherename='小米科技';6.5.3FORCEINDEX要强制MySQL使用特定的索引,可以在查询中使用forceindex作为提示。在tb_seller(address)上创建索引idx_seller_address;解释select*fromtb_sellerforceindex(idx_seller_address)whereaddress='北京';如果本文对您有帮助,请关注并点赞;有什么建议也可以留言或私信。您的支持是我坚持创作的动力