使⽤查询结果作为插⼊字段_SQL指南:如何优化SQL查询本⽂分类了⼀些优化SQL查询的特殊技术
在本⽂中,我提供了⼀些有关优化SQL语句的建议,其中⼤多数建议在实际开发中进⾏了总结。 希望对⼤家有帮助。
我们的⽬标是使查询的执⾏情况令⼈满意,并在以后的合理时间内继续这样做
> Photo by Nick Morrison on Unsplash
更新:我在GitHub Repo中上传了所有优化技巧
1.尽量不要使⽤select *查询SQL,⽽是选择特定字段。
反例:
select * from employee;
正⾯⽰例:
select id,name from employee;
原因:
· 通过仅使⽤必填字段,我们可以节省资源并减少⽹络开销。
· 可能不会使⽤covered索引,这将导致查询返回到表。
2.如果您知道只有⼀个查询结果,建议使⽤限制1
假设有⼀个雇员表,并且您想到⼀个名为jay的⼈。
CREATE TABLE employee (id int(11) NOT NULL,name varchar(255) DEFAULT NULL,age int(11) DEFAULT NULL,date datetime DEFAULT NULL,sex int(1) DEFAULT NULL,PRIMARY KEY (`id`) );
反例:
select id,name from employee where name='jay';
正⾯⽰例:
select id,name from employee where name='jay' limit 1;
原因:
· 添加限制1后,如果到相应的记录,它将不再继续扫描,效率将⼤⼤提⾼。
3.尝试避免使⽤或在where⼦句中加⼊条件
创建⼀个新的⽤户表,它具有公⽤索引userId,该表的结构如下:
CREATE TABLE `user` ( `id` int(11) NOT NULL AUTO_INCREMENT, `userId` int(11) NOT NULL, `age` int(11) NOT NULL,
`name` varchar(255) NOT NULL, PRIMARY KEY (`id`), KEY `idx_userId` (`userId`) )
现在假设您需要查询⽤户ID为1或18岁的⽤户,使⽤以下SQL很容易。
反例:
select * from user where userid = 1 or age = 18;
正⾯⽰例:
//Use union all
select * from user where userid=1 union all select * from user where age = 18;
//Or write two separate SQL
select * from user where userid=1;
select * from user where age = 18;
原因:
· 使⽤或可能会使索引⽆效,因此需要进⾏全表扫描。
对于有索引或⽆索引的情况,假定已采⽤userId的索引,但是当涉及到年龄查询条件时,它必须执⾏全表扫描,这需要三步过程:全表扫描+索引扫描+合并
4.优化限制分页
进⾏⽇常分页时,通常使⽤限制来实现,但是当偏移量特别⼤时,查询效率会降低。 因为Mysql不会跳过偏移量,⽽是直接获取数据。
反例:
select id,name,age from employee limit 10000,10;
正⾯⽰例:
//Solution 1: Return the largest record (offset) of the last query
select id,name from employee where id>10000 limit 10;
//Solution 2: order by + index
select id,name from employee order by id limit 10000,10;
原因:
· 如果使⽤优化解决⽅案1,它将返回上⼀个查询记录(偏移量),以便您可以跳过偏移量,效率得到了很⼤的提⾼。
· 选项⼆使⽤按+索引排序,这也可以提⾼查询效率。
5.优化喜欢的陈述
在⽇常开发中,如果使⽤模糊关键字查询,则很容易想到"赞",但是"赞"可能会使索引⽆效。
反例:
select userId,name from user where userId like '%123';
正⾯⽰例:
select userId,name from user where userId like '123%';
原因:在这个故事中
6.使⽤where条件限制要查询的数据,以避免返回多余的⾏
假设⽅案为"查询⽤户是否为成员"。 我已经看到了这样的旧的实现代码。
反例:
List userIds = sqlMap.queryList("select userId from user where isVip=1");
boolean isVip = user
正⾯⽰例:
Long userId = sqlMap.queryObject("select userId from user where userId='userId' and isVip='1' ")
boolean isVip = user
Id!=null;
原因:检查需要哪些数据,避免返回不必要的数据,并节省费⽤和计算开销
7.您应尽可能避免在where⼦句中使⽤!=或<>运算符,否则引擎将放弃使⽤索引并执⾏全表扫描
反例:
select age,name from user where age <>18;
正⾯⽰例:
//You can consider separate two sql write
select age,name from user where age <18;
select age,name from user where age >18;
原因:使⽤!=和<>可能会使索引⽆效
8.如果插⼊太多数据,请考虑批量插⼊
如果要插⼊太多数据,请考虑批量插⼊
反例:
for(User u :list){ INSERT into user(name,age) values(#name#,#age#) }
正⾯⽰例:
//One batch of 500 inserts, carried out in batchesinsert into user(name,age) values (#{item.name},#{item.age})
· 批量插⼊性能好,省时
打个⽐⽅:如果您需要将10,000块砖移动到建筑物的顶部,则可以使⽤电梯。
电梯⼀次可以放置适当数量的砖块(最多500块),您可以选择⼀次运输⼀块砖块,也可以⼀次运输500块砖块。 您认为哪个时间昂贵?
9.谨慎使⽤distinct关键字
通常,distinct关键字⽤于过滤重复记录以返回唯⼀记录。 当⽤于查询⼀个或⼏个字段时,它将为查询带来优化效果。
但是,当字段很多时,将⼤⼤降低查询效率。
反例:
SELECT DISTINCT * from user;
正⾯⽰例:
select DISTINCT name from user;
原因:具有"不区分⼤⼩写"的语句的CPU时间和占⽤时间⽐没有"不区分⼤⼩写"的语句⾼。
因为在查询许多字段时,如果使⽤不重复,数据库引擎将⽐较数据并过滤出重复的数据。 但是,此⽐较和筛选过程将消耗系统资源和CPU 时间。
10.删除冗余和重复的索引
反例:
KEY `idx_userId` (`userId`) KEY `idx_userId_age` (`userId`,`age`)
正⾯⽰例:
//Delete the userId index, because the combined index (A, B) is equivalent to creating the (A) and (A, B) indexes
KEY `idx_userId_age` (`userId`,`age`)
原因:重复的索引需要维护,优化器在优化查询时也需要⼀⼀考虑,这会影响性能。
11.如果数据量很⼤,请优化您的修改/删除语句
避免同时修改或删除太多数据,因为这会导致CPU利⽤率⾼,从⽽影响其他⼈对数据库的访问。
反例:
//Delete 100,000 or 1 million+ at a time?批量更新sql语句
delete from user where id <100000;
//Or use single cycle operation, low efficiency and long time
for(User user:list){ delete from user; }
正⾯⽰例:
//Delete in batches, such as 500 each timedelete user where id<500;delete product where id>=500 and id<1000;
原因:要⼀次删除太多数据,可能有⼀个锁定等待超时超过错误,因此建议分批操作。
12.考虑在where⼦句中使⽤默认值⽽不是null
反例:
select * from user where age is not null;
正⾯⽰例:
select * from user where age>0; //Set 0 as default
原因:
· 如果将空值替换为默认值,则通常可以建⽴索引,与此同时,表达式将相对清晰。
13.尝试⽤⼯会全部代替⼯会
如果搜索结果中没有重复的记录,建议将union替换为union all。
反例:
select * from user where userid=1 union select * from user where age = 10
正⾯⽰例:
select * from user where userid=1 union all select * from user where age = 10
原因:
· 如果使⽤联合,则⽆论是否重复搜索结果,它都会尝试合并并排序它们,然后输出最终结果。
· 如果已知搜索结果没有重复的记录,请使⽤union all⽽不是union,这将提⾼效率。
14.尽可能使⽤数字字段。如果字段仅包含数字信息,请尝试不要将其设计为字符类型。
反例:
`king_id` varchar(20) NOT NULL;
正⾯⽰例:
`king_id` int(11) NOT NULL;
原因:与数字字段相⽐,字符类型会降低查询和连接的性能,并会增加存储开销。
15.尽可能使⽤varchar / nvarchar代替char / nchar
反例:
`deptName` char(100) DEFAULT NULL
正⾯⽰例:
`deptName` varchar(100) DEFAULT NULL
原因:
· ⾸先,由于可变长度字段的存储空间很⼩,因此可以节省存储空间。
· 其次,对于查询,在相对较⼩的字段中进⾏搜索更为有效。
16.使⽤说明来分析您的SQL计划
在⽇常开发中编写SQL时,请养成习惯。 使⽤说明来分析您编写的SQL,尤其是索引。
explain select * from user where userid = 10086 or age =18;
是的,我们做到了最后。 希望您喜欢它,并对优化和加快SQL查询有个想法
Other stories you'll love* Related to optimization of File Handling - How to do Efficient File Handl
感谢您的阅读。 不要犹豫,继续关注更多!
如果您想加⼊,我会每⽉发送⼀次通讯,请通过此链接注册。 爱见你
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论