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

SQL优化,怎么做?

时间:2023-03-14 16:52:07 科技观察

1.insert优化批量插入insertintotb_namevalues(1,"张三"),(2,"张三"),(3,"张三");手动提交事务,因为mysql默认的事务提交方式是Automaticcommit,意思是当我们执行insert语句时,事务自动提交,可能会频繁涉及到事务的启动和提交,所以建议手动控制交易。starttransaction;insertintotb_namevalues(1,"张三"),(2,"张三"),(3,"张三");insertintotb_namevalues(4,"张三"),(5,"张三"),(6,"张三");插入tb_name值(7,"张三"),(8,"张三"),(9,"张三");commit;primarykeyorder主键插入顺序插入的性能要高于乱序插入,这取决于MySQL的数据组织结构。插入大批量数据如果需要一次性插入大批量数据,使用insert语句插入性能较低。这时候可以使用MySQL数据库提供的load命令进行插入。操作如下:#客户端连接服务器时,添加参数--local-infilemysql--local-infile-Uroot-p#设置全局参数localinfile为1,打开开关从mysql导入数据本地加载文件setgloballocalinfile=1;#执行加载命令,将准备好的数据加载到表结构中。使用加载命令时,主键顺序插入的性能高于随机插入loaddatalocalinfile'/xxx/sql.log'intotable'tb_name'fieldsterminatedby','linesterminatedby'\n';/xxx/sql.log:待加载的本地文件tb_name:表名,:字段分隔符\n:行分隔符2.主键SQL优化数据组织在InnoDB存储引擎中,表数据按照顺序组织存储首要的关键。这种存储方式下的表称为索引组织表(indexorganizedtableIOT)。页面拆分页面可以是空的、半填充的或100%填充的。每页包含2-N行数据(如果一行数据过多会溢出),按照主键排列。页面合并当一行被删除时,记录实际上并没有被物理删除,但记录被标记为删除并且它的空间可供其他记录声明使用。当页面上删除的记录达到MERGE_THRESHOLD(默认为页面的50%)时,InnoDB将开始寻找最近的页面(之前或之后)以查看是否可以合并两个页面以优化空间使用。在满足业务需求的情况下,尽量减小主键的长度。在满足业务需求的情况下,尽量减小主键的长度。插入数据时尽量选择顺序插入,选择使用AUTO_INCREMENT自增主键。在业务运行过程中,避免修改主键。3.Orderbyoptimization①使用filesort:通过表索引或者全表扫描,读取满足条件的数据行,然后在排序缓冲区sortbuffer中完成排序操作。所有不直接通过索引返回排序结果的排序都称为FileSort排序。②使用索引:顺序扫描有序索引直接返回有序数据。本例使用using索引,不需要额外排序,运行效率高。#没有创建索引时,按照age,phone排序selectid,age,phonefromtb_userorderbyage,phone;#创建索引createindexidx_user_age_phone_aaontb_user(age,phone);#创建索引后,根据age,Phoneissortedinaskendingorderexplainselectid,age,phonefromtb_userorderbyage,phone;#创建索引后,按照age和phone降序排列explainselectid,age,phonefromtb_userorderbyagedesc,phonedesc;#根据年龄,电话降序一个升序,一个降序说明selectid,age,phonefromtb_userorderbyageasc,phonedesc;#createindexcreateindexidx_user_age_hone_adontb_user(ageasc,phonedesc);#根据年龄,电话降序一个升序,一个降序说明selectid,age,phonefromtb_userorderbyageasc,phonedesc;根据排序字段建立合适的索引,多字段排序时遵循最左前缀规则。尽可能使用覆盖索引。对于多字段排序,一升一降,创建联合索引时需要注意规则(ASC/DESC)。如果无法避免filesort,在对大量数据进行排序时,可以适当增大排序缓冲区sort_buffer_size的大小(默认256k)。4.groupby优化#进行分组操作,groupbyprofession字段说明selectprofession,count(*)fromtb_usergroupbyprofession;#CreateindexCreateindexidx_user_pro_age_staontb_user(profession,age,status);#进行分组操作,根据到专业字段分组解释选择专业,从tb_user组按专业计数(*);#进行分组操作,groupbyprofessionfieldexplainselectprofession,count(*)fromtb_usergroupbyprofession,age;在分组操作时,可以使用索引来提高效率。在分组操作中,索引的使用也满足最左前缀规则。5.极限优化一个常见而且很头疼的问题就是极限2000000,10。这时MySQL需要对前2000010条记录进行排序,只返回2000000-2000010条记录,丢弃其他记录。查询排序的成本非常高。优化思路:在一般的分页查询中,通过创建覆盖索引可以更好的提升性能??,可以通过在覆盖索引上增加子查询来进行优化。如:explainselectfromtb_skut,(selectidfromtb__skuorderbyidlimit2000000,10)awheret.id=a.id;六、count优化explainselectcount(*)fromtbuser;MyISAM引擎把一个表的总行数存在磁盘上,所以在执行count(*)时,会直接返回这个数,效率很高;InnoDB引擎出问题了,当它执行count(*)时,需要把数据逐行从引擎中读取出来,然后累加count。优化思路:自己算。可配合多种再贴现用途。count()是一个聚合函数。对于返回的结果集,逐行判断。如果count函数的参数不为NULL,则累计值加1,否则不加,最后返回累计值。用法:count(*)、count(主键)、count(字段)、count(1)。count(primarykey)InnoDB引擎会遍历整张表,取出每一行的主键id值,返回给服务层。服务层拿到主键后,直接按行累加(主键不能为null)。count(field)没有非空约束:InnoDB引擎会遍历整张表,提取每一行的字段值返回给服务层。服务层判断是否为null,向上计数。没有空约束:InnoDB引擎会遍历整张表,提取每一行的字段值,返回给服务层,直接逐行累加。count(1)InnoDB引擎遍历整张表,但不取值。对于返回的每一行,服务层将一个数字“1”放入其中,并直接按行累加。count(*)InnoDB引擎并没有把所有的字段都取出来,而是专门优化了一下,不取值,服务层直接按行累加。为了效率,count(field)