SQL优化
oracle sql 优化技巧

oracle sql 优化技巧(实用版3篇)目录(篇1)1.Oracle SQL 简介2.优化技巧2.1 减少访问数据库次数2.2 选择最有效率的表名顺序2.3 避免使用 SELECT2.4 利用 DECODE 函数2.5 设置 ARRAYSIZE 参数2.6 使用 TRUNCATE 替代 DELETE2.7 多使用 COMMIT 命令2.8 合理使用索引正文(篇1)Oracle SQL 是一款广泛应用于各类大、中、小微机环境的高效、可靠的关系数据库管理系统。
为了提高 Oracle SQL 的性能,本文将为您介绍一些优化技巧。
首先,减少访问数据库的次数是最基本的优化方法。
Oracle 在内部执行了许多工作,如解析 SQL 语句、估算索引的利用率、读数据块等,这些都会大量耗费 Oracle 数据库的运行。
因此,尽量减少访问数据库的次数,可以有效提高系统性能。
其次,选择最有效率的表名顺序也可以明显提升 Oracle 的性能。
Oracle 解析器是按照从右到左的顺序处理 FROM 子句中的表名,因此,合理安排表名顺序,可以减少解析时间,提高查询效率。
在执行 SELECT 子句时,应尽量避免使用,因为 Oracle 在解析的过程中,会将依次转换成列名,这是通过查询数据字典完成的,耗费时间较长。
DECODE 函数也是一个很好的优化工具,它可以避免重复扫描相同记录,或者重复连接相同的表,提高查询效率。
在 SQLPlus 和 SQLForms 以及 ProC 中,可以重新设置 ARRAYSIZE 参数。
该参数可以明显增加每次数据库访问时的检索数据量,从而提高系统性能。
建议将该参数设置为 200。
当需要删除数据时,尽量使用 TRUNCATE 语句替代 DELETE 语句。
执行 TRUNCATE 命令时,回滚段不会存放任何可被恢复的信息,所有数据不能被恢复。
因此,TRUNCATE 命令执行时间短,且资源消耗少。
在使用 Oracle 时,尽量多使用 COMMIT 命令。
SQL优化--inner、leftjoin替换in、notin、except

SQL优化--inner、leftjoin替换in、notin、except新系统上线,⽤户基数16万,各种查询timeout。
打开砂锅问到底,直接看sql语句吧,都是泪呀,⼀⼤堆in\not in\except。
这⾥总结⼀下,怎么替换掉in\not in\except。
1. in/except->left join查询⽬的:根据客户表(Customer,按照站点、册本划分,16万数据)⽔表表(Meter,16万数据)⽔表抄表数据表(Meter_Data,远传表每天更新,27万数据)关联查询,查询某天某个册本下⽔表未上传抄表数据的⽤户。
原查询结构select *from Customer cswherecs.Group_No = '册本编号' andcs.Customer_No in(select Customer_Nofrom Customer csleft join Meter me on cs.Customer_No = me.Customer_Nowhere cs.Group_No = '册本编号'exceptselect Customer_Nofrom Customer csleft join Meter me on cs.Customer_No = me.Customer_Noinner join Meter_data md on me.meter_no = md.meter_no and md.date = '2019-04-09'where cs.Group_NO='册本编号')原查询思路1. 查询出⽬标册本已上传数据的⽤户编号select Customer_Nofrom Customer csleft join Meter me on cs.Customer_No = me.Customer_Noinner join Meter_data md on me.meter_no = md.meter_no and md.date = '2019-04-09'where cs.Group_NO='册本编号'2. 查询出⽬标册本全部⽤户编号select Customer_Nofrom Customer csleft join Meter me on cs.Customer_No = me.Customer_Nowhere cs.Group_No = '册本编号'3. 全部⽤户编号中排除已上传数据的⽤户编号,即为未上传数据的⽤户编号全部⽤户编号 except 已抄表的⽤户编号4. 查询出在未抄表⽤户编号集合中的⽤户信息。
SQL优化工具及使用技巧介绍

SQL优化工具及使用技巧介绍SQL(Structured Query Language)是一种用于管理和操作关系型数据库的编程语言。
它可以让我们通过向数据库服务器发送命令来实现数据的增删改查等操作。
然而,随着业务的发展和数据量的增长,SQL查询的性能可能会受到影响。
为了提高SQL查询的效率,出现了许多SQL优化工具。
本文将介绍一些常见的SQL优化工具及其使用技巧。
一、数据库性能优化工具1. Explain PlanExplain Plan是Oracle数据库提供的一种SQL优化工具,它可以帮助分析和优化SQL语句的执行计划。
通过使用Explain Plan命令,我们可以查看SQL查询的执行计划,了解SQL语句是如何被执行的,从而找到性能瓶颈并进行优化。
2. SQL Server ProfilerSQL Server Profiler是微软SQL Server数据库管理系统的一种性能监视工具。
它可以捕获和分析SQL Server数据库中的各种事件和耗时操作,如查询语句和存储过程的执行情况等。
通过使用SQL Server Profiler,我们可以找到数据库的性能瓶颈,并进行相应的优化。
3. MySQL Performance SchemaMySQL Performance Schema是MySQL数据库提供的一种性能监视工具。
它可以捕获和分析MySQL数据库中的各种事件和操作,如查询语句的执行情况、锁的状态等。
通过使用MySQL Performance Schema,我们可以深入了解数据库的性能问题,并对其进行优化。
二、SQL优化技巧1. 使用索引索引是提高SQL查询性能的重要手段之一。
在数据库中创建合适的索引可以加快查询操作的速度。
通常,我们可以根据查询条件中经常使用的字段来创建索引。
同时,还应注意索引的维护和更新,避免过多或过少的索引对性能产生负面影响。
2. 避免全表扫描全表扫描是指对整个表进行扫描,如果表中数据量较大,查询性能会受到较大影响。
通过分析SQL语句的执行计划优化SQL

通过分析SQL语句的执行计划优化SQL
1.确定问题SQL:首先要确定哪个SQL语句是需要优化的,可以根据
数据库性能监控或慢查询日志等方式来定位。
2.分析执行计划:执行计划是数据库查询优化的关键,通过分析执行
计划可以了解SQL查询使用的索引、连接方式、数据访问路径等重要信息。
3.选择合适的索引:根据执行计划中的信息,考虑是否需要添加或修
改索引。
适当的索引可以大大提高查询性能,但是过多或不合适的索引也
会拖慢性能。
4.避免全表扫描:全表扫描是非常低效的操作,可以通过添加合适的
索引来避免全表扫描,或者优化查询条件使得数据库可以利用索引进行查询。
5.利用查询缓存:数据库中可能存在查询缓存,可以将频繁查询的SQL语句缓存起来,提高查询性能。
6.合理使用子查询:子查询可以增加数据访问的复杂性,需要谨慎使用。
可以重写SQL语句,将子查询转换为连接查询或者使用临时表等方式
避免子查询的使用。
7.调整SQL语句的顺序:在复杂的SQL语句中,表的连接顺序会影响
查询性能。
可以通过调整表的连接顺序,使得执行计划更为高效。
8.数据库优化:除了优化SQL语句,还可以从数据库本身进行优化,
比如调整数据库的参数配置,增加硬件资源等方式来提高数据库性能。
总之,通过分析SQL语句的执行计划,结合合适的索引和优化技巧,
可以大大提高SQL查询的性能。
SQL优化之limit1

SQL优化之limit1 在某些情况下,如果明知道查询结果只有⼀个,SQL语句中使⽤LIMIT 1会提⾼查询效率。 例如下⾯的⽤户表(主键id,邮箱,密码):
1 create table t_user( 2 id int primary key auto_increment, 3 email varchar(255), 4 password varchar(255) 5 );
每个⽤户的email是唯⼀的,如果⽤户使⽤email作为⽤户名登陆的话,就需要查询出email对应的⼀条记录。 1 SELECT * FROM t_user WHERE email=?;
上⾯的语句实现了查询email对应的⼀条⽤户信息,但是由于email这⼀列没有加索引,会导致全表扫描,效率会很低。 1 SELECT * FROM t_user WHERE email=? LIMIT 1;
加上LIMIT 1,只要找到了对应的⼀条记录,就不会继续向下扫描了,效率会⼤⼤提⾼。 LIMIT 1适⽤于查询结果为1条(也可能为0)会导致全表扫描的的SQL语句。
如果email是索引的话,就不需要加上LIMIT 1,如果是根据主键查询⼀条记录也不需要LIMIT 1,主键也是索引。 例如:
1 SELECT * FROM t_user WHERE id=?;
就不需要写成: 1 SELECT * FROM t_user WHERE id=? LIMIT 1;
⼆者效率没有区别。 存储过程⽣成100万条数据: 1 BEGIN 2 DECLARE i INT; 3 START TRANSACTION; 4 SET i=0; 5 WHILE i<1000000 DO 6 INSERT INTO t_user VALUES(NULL,CONCAT(i+1,'@xxg.com'),i+1); 7 SET i=i+1; 8 END WHILE; 9 COMMIT; 10 END
SQL优化的几种方法及总结

SQL优化的⼏种⽅法及总结优化⼤纲:通过explain 语句帮助选择更好的索引和写出更优化的查询语句。
SQL语句中的IN包含的值不应该过多。
当只需要⼀条数据的时候,使⽤limit 1。
如果限制条件中其他字段没有索引,尽量少⽤or。
尽量⽤union all代替union。
不使⽤ORDER BY RAND()。
区分in和exists、not in和not exists。
使⽤合理的分页⽅式以提⾼分页的效率。
查询的数据过⼤,可以考虑使⽤分段来进⾏查询。
避免在where⼦句中对字段进⾏null值判断。
避免在where⼦句中对字段进⾏表达式操作。
必要时可以使⽤force index来强制查询⾛某个索引。
注意查询范围,between、>、<等条件会造成后⾯的索引字段失效。
关于JOIN优化。
优化使⽤1、mysql explane ⽤法 explane显⽰了mysql如何使⽤索引来处理select语句以及连接表。
可以帮助更好的索引和写出更优化的查询语句。
EXPLAIN SELECT*FROM l_line WHERE `status` =1and create_at >'2019-04-11';explain字段列说明table:显⽰这⼀⾏的数据是关于哪张表的type:这是重要的列,显⽰连接使⽤了何种类型。
从最好到最差的连接类型为const、eq_reg、ref、range、indexhe和allpossible_keys:显⽰可能应⽤在这张表中的索引。
如果为空,没有可能的索引。
可以为相关的域从where语句中选择⼀个合适的语句key:实际使⽤的索引。
如果为null,则没有使⽤索引。
很少的情况下,mysql会选择优化不⾜的索引。
这种情况下,可以在select语句中使⽤use index(indexname)来强制使⽤⼀个索引或者⽤ignore index(indexname)来强制mysql忽略索引key_len:使⽤的索引的长度。
SQL优化----百万数据查询优化
SQL优化----百万数据查询优化百万数据查询优化1.合理使⽤索引 索引是数据库中重要的数据结构,它的根本⽬的就是为了提⾼查询效率。
现在⼤多数的数据库产品都采⽤IBM最先提出的ISAM索引结构。
索引的使⽤要恰到好处,其使⽤原则如下: ●在经常进⾏连接,但是没有指定为外键的列上建⽴索引,⽽不经常连接的字段则由优化器⾃动⽣成索引。
●在频繁进⾏排序或分组(即进⾏group by或order by操作)的列上建⽴索引。
●在条件表达式中经常⽤到的不同值较多的列上建⽴检索,在不同值少的列上不要建⽴索引。
⽐如在雇员表的“性别”列上只有“男”与“⼥”两个不同值,因此就⽆必要建⽴索引。
如果建⽴索引不但不会提⾼查询效率,反⽽会严重降低更新速度。
●如果待排序的列有多个,可以在这些列上建⽴复合索引(compound index)。
●使⽤系统⼯具。
如Informix数据库有⼀个tbcheck⼯具,可以在可疑的索引上进⾏检查。
在⼀些数据库服务器上,索引可能失效或者因为频繁操作⽽使得读取效率降低,如果⼀个使⽤索引的查询不明不⽩地慢下来,可以试着⽤tbcheck⼯具检查索引的完整性,必要时进⾏修复。
另外,当数据库表更新⼤量数据后,删除并重建索引可以提⾼查询速度。
2.避免或简化排序 应当简化或避免对⼤型表进⾏重复的排序。
当能够利⽤索引⾃动以适当的次序产⽣输出时,优化器就避免了排序的步骤。
以下是⼀些影响因素: ●索引中不包括⼀个或⼏个待排序的列; ●group by或order by⼦句中列的次序与索引的次序不⼀样; ●排序的列来⾃不同的表。
为了避免不必要的排序,就要正确地增建索引,合理地合并数据库表(尽管有时可能影响表的规范化,但相对于效率的提⾼是值得的)。
如果排序不可避免,那么应当试图简化它,如缩⼩排序的列的范围等。
3.消除对⼤型表⾏数据的顺序存取 在嵌套查询中,对表的顺序存取对查询效率可能产⽣致命的影响。
⽐如采⽤顺序存取策略,⼀个嵌套3层的查询,如果每层都查询1000⾏,那么这个查询就要查询10亿⾏数据。
SQL优化技巧与性能调优考试
SQL优化技巧与性能调优考试(答案见尾页)一、选择题1. SQL优化中,哪项操作可以减少磁盘I/O?A. 使用索引B. 使用SELECT *C. 使用子查询D. 使用JOIN2. 在进行SQL优化时,以下哪个操作可以提高查询性能?A. 为经常一起使用的列创建索引B. 使用SELECT COUNT(*)而不是COUNT(1)C. 避免使用外键D. 尽量避免在WHERE子句中使用函数3. 为了提高SQL查询的性能,应该在哪些情况下使用存储过程?A. 当需要执行复杂的计算时B. 当需要多次执行相同的查询时C. 当需要从多个表中获取数据时D. 当需要对数据进行加密时4. 在SQL优化中,如何减少查询中的冗余数据?A. 使用DISTINCT关键字B. 使用GROUP BY子句C. 使用HAVING子句D. 使用LIMIT子句5. 对于大型数据库,使用哪种类型的索引效果最好?A. 主键索引B. 唯一索引C. 普通索引D. 全文索引6. 在进行SQL查询优化时,应该避免哪种类型的子查询?A. 相关子查询B. 非相关子查询C. 标量子查询D. 表子查询7. 为了提高查询性能,应该在哪些列上创建索引?A. 经常用于WHERE子句的列B. 经常用于ORDER BY子句的列C. 经常用于JOIN条件的列D. 经常用于GROUP BY子句的列8. 在SQL优化中,如何处理包含NULL值的列?A. 在查询中使用COALESCE函数B. 将NULL值替换为特定的默认值C. 删除包含NULL值的行D. 不要对该列进行索引9. 在SQL优化中,如何避免死锁?A. 使用锁定超时B. 减少事务的大小和范围C. 使用更高的隔离级别D. 避免长时间运行的事务10. 在进行SQL性能调优时,以下哪个选项不是常见的性能瓶颈?A. 硬件资源限制(如CPU、内存、磁盘I/O)B. 数据库设计不合理C. SQL查询效率低下D. 网络延迟11. 在SQL查询中,使用哪个子句可以帮助我们限制返回的结果集?A. SELECTB. FROMC. WHERED. GROUP BY12. 为了提高查询性能,我们应该尽量避免使用哪种类型的子查询?A. 相关子查询B. 非相关子查询C. 标量子查询D. 表子查询13. 在进行SQL优化时,通常建议避免使用哪种类型的连接操作?A. INNER JOINB. OUTER JOINC. CROSS JOIND. self JOIN14. 对于大型数据表,使用哪个命令可以帮助我们查看表的行数和列数?A. DESCRIPTIVE TABLEB. TABLE DETAILSC. INFORMATION_SCHEMA.TABLESD. TABLE SUMMARIES15. 在SQL优化中,哪种类型的索引最适合用于经常作为查询条件使用的列?A. 主键索引B. 唯一索引C. 非唯一索引D. 全文索引16. 当需要对查询进行优化时,以下哪种方法可以用来分析查询的执行计划?A. EXPLAINB. DESCRIPTIVE TABLEC. QUERY ANALYZERD. SQL TRACE17. 在SQL优化中,哪种技术可以用来合并多个结果集,并减少查询中的JOIN操作?A. UNION ALLB. UNIONC. JOIND. GROUP BY18. 对于包含大量重复数据的表,哪个SQL命令可以帮助我们删除重复行?A. DELETEB. TRUNCATEC. DISTINCTD. SELECT DISTINCT19. 在SQL优化中,哪种技术通常用于处理非常小的数据集,并提高查询性能?A. 分区B. 触发器C. 索引D. 视图20. 在进行SQL优化时,以下哪种情况通常不建议使用索引?A. 经常用于查询条件B. 经常用于排序的列C. 经常用于WHERE子句的列D. 经常用于JOIN操作的列21. 在进行SQL优化时,哪种类型的索引最适合用于经常作为查询条件的列?A. 主键索引B. 唯一索引C. 全文索引D. 组合索引22. 以下哪个SQL语句通常会导致查询性能下降?A. 使用SELECT * 查询所有列B. 在WHERE子句中使用函数C. 对大型表进行全表扫描D. 使用连接(JOIN)操作23. 当需要对查询结果进行分组时,使用哪种关键字可以实现分组并保留分组统计信息?A. GROUP BYB. ORDER BYC. HAVINGD. LIMIT24. 在SQL优化中,如何提高查询性能?(多选)A. 避免使用SELECT *,只选择需要的列B. 使用连接(JOIN)代替子查询C. 对频繁一起使用的列创建组合索引D. 尽量减少查询中的条件数量25. 在进行SQL优化时,如何避免SQL注入攻击?A. 使用参数化查询B. 使用存储过程C. 对用户输入进行严格验证D. 尽量避免使用动态SQL26. SQL优化中,如何处理大量数据的插入操作?A. 使用批量插入B. 使用事务C. 关闭自动提交D. 批量读取和写入27. 在进行SQL优化时,如何确定是否需要调整查询性能?A. 检查查询执行时间B. 分析查询计划C. 观察数据库服务器的性能指标D. 以上都是28. 在SQL优化中,如何处理复杂的嵌套查询?A. 尽量避免使用嵌套查询B. 将嵌套查询转换为连接(JOIN)操作C. 对于简单嵌套查询,可以使用子查询优化器D. 将嵌套查询分解为多个查询29. 在SQL优化中,如何对查询进行缓存以提高性能?A. 使用SQL缓存B. 使用数据库的查询缓存功能C. 将查询结果保存到缓存文件中D. 使用外部缓存工具30. SQL优化中,哪项操作可以减少磁盘I/O次数?A. 使用索引B. 增加数据冗余C. 优化查询语句D. 减少数据量31. 以下哪个因素通常不是导致SQL查询性能下降的原因?A. 数据库表过大B. 硬件资源不足C. 索引过多D. 查询语句过于复杂32. 为了提高查询效率,SQL优化中常采用哪些方法来减少数据传输量?A. 利用分页技术B. 减少返回的数据量C. 使用存储过程D. 批量插入数据33. 在SQL优化中,如何确定是否需要使用分区表?A. 当表中的数据量非常大时B. 当表的访问模式呈现倾斜时C. 当需要提高查询性能时D. 当需要对数据进行备份和恢复时34. 以下关于SQL查询缓存的说法,哪项是不正确的?A. 查询缓存可以显著提高查询性能B. 查询缓存对于包含大量重复数据的查询无效C. 查询缓存需要定期维护D. 查询缓存在所有数据库系统中都可用35. 在进行SQL优化时,如何处理复杂的嵌套查询?A. 尽可能将嵌套查询转换为连接查询B. 将嵌套查询提取为子查询C. 避免使用嵌套查询D. 使用临时表来简化嵌套查询36. 以下哪种情况下,使用EXPLAIN命令可以帮助分析查询性能?A. 查询涉及多个表B. 查询结果集非常大C. 查询执行计划不明确D. 查询性能已经非常优化37. 在SQL优化中,如何避免过度扫描索引?A. 合理设计索引B. 优化查询条件C. 使用覆盖索引D. 避免在WHERE子句中使用函数38. 为了提高SQL查询的性能,数据库管理员应该定期执行哪些操作?A. 分析查询日志B. 清理无用数据C. 调整数据库参数D. 重新创建索引39. 在进行SQL优化时,对查询语句进行优化的主要目的是什么?A. 提高查询效率B. 减少查询时间C. 提高数据完整性D. 减少网络带宽消耗40. 以下哪个因素不是SQL优化中需要考虑的因素?A. 硬件资源限制B. 数据库服务器的性能C. 查询的具体内容D. 数据库管理员的技能水平41. 在SQL优化中,通常建议避免使用哪种类型的子查询?A. 相关子查询B. 非相关子查询C. 标量子查询D. 表子查询42. 对于频繁一起使用的列,最好的做法是:A. 使用函数计算它们的和或平均值B. 将它们合并到一个表中C. 为它们创建索引D. 使用视图43. 以下哪种方法可以帮助在查询中减少使用子查询?A. 使用CASE语句B. 使用JOIN代替子查询C. 使用临时表D. 使用聚合函数44. 在SQL优化中,对索引的要求是:A. 只要使用了索引,就一定能提高查询效率B. 索引越多越好C. 应该根据查询需求合理地创建和使用索引D. 不需要考虑索引的开销45. 以下哪个选项不是SQL优化中常见的策略?A. 利用存储过程B. 使用存储过程C. 优化查询语句D. 增加数据冗余46. 在进行SQL优化时,如何判断是否需要对某个表的某个列添加索引?A. 观察查询计划中的访存次数B. 直接在表上添加索引C. 查看系统的IO统计信息D. 计算该列的唯一值数量47. 在SQL优化中,如何处理大型数据集的加载?A. 直接在原表上进行大量数据导入B. 使用批量插入数据的方法C. 使用数据导入工具D. 将数据分批导入二、问答题1. 什么是SQL优化?为什么我们需要对SQL进行优化?2. 在哪些情况下应该考虑对SQL进行优化?3. SQL优化的主要目标是什么?4. 有哪些常见的SQL优化技巧?5. 如何使用EXPLAIN命令来分析SQL查询性能?6. 什么是索引?为什么我们要使用索引?7. 如何创建和使用索引?8. 什么是数据库范式?为什么我们要遵循数据库范式?参考答案选择题:1. A2. A3. B4. A5. C6. B7. AC8. A9. ABCD 10. D11. C 12. D 13. C 14. C 15. A 16. A 17. A 18. D 19. D 20. B21. C 22. B 23. A 24. ABCD 25. ACD 26. ABC 27. D 28. ABC 29. B 30. A31. D 32. AB 33. ABC 34. D 35. A 36. ABC 37. ABCD 38. ABC 39. A 40. D41. B 42. C 43. B 44. C 45. D 46. A 47. B问答题:1. 什么是SQL优化?为什么我们需要对SQL进行优化?SQL优化是指通过调整SQL查询语句和数据库设计来提高数据库查询性能的过程。
SQL查询优化考试试卷
SQL查询优化考试试卷(答案见尾页)一、选择题1. SQL查询优化的目的是什么?A. 提高查询速度B. 增加数据库负担C. 减少数据冗余D. 降低系统稳定性2. 在进行SQL查询优化时,以下哪个不是常用的优化方法?A. 使用分区表B. 使用存储过程C. 尽量避免使用SELECT *D. 避免使用子查询3. 以下哪个不是索引的作用?A. 提高查询速度B. 增加数据冗余C. 加速表之间的连接D. 减少查询所需的时间4. 在SQL查询优化中,通常建议避免使用哪种类型的子查询?A. 相关子查询B. 非相关子查询C. 标量子查询D. 表子查询5. 在SQL查询优化中,使用哪个命令可以帮助分析查询性能?A. EXPLAINB. DESCRIPTORC. ANALYZED. PROFILE6. 以下哪个因素可能导致SQL查询性能下降?A. 数据库服务器硬件故障B. 数据库表空间不足C. 索引过多或缺失D. 查询语句语法错误7. 在进行SQL查询优化时,如何确定是否需要优化?A. 查看查询执行时间B. 分析查询计划C. 询问开发人员D. 直接修改查询语句8. 在SQL查询优化中,通常建议使用哪种类型的连接(INNER JOIN)?A. 左连接(LEFT JOIN)B. 右连接(RIGHT JOIN)C. 内连接(INNER JOIN)D. 外连接(OUTER JOIN)9. 在SQL查询优化中,如何减少查询中的数据量?A. 使用LIMIT子句B. 使用WHERE子句过滤C. 使用JOIN代替子查询D. 使用GROUP BY和HAVING子句10. 在SQL查询优化中,如何提高查询结果的准确性?A. 使用正则表达式B. 使用聚合函数C. 使用视图(VIEW)D. 使用触发器(TRIGGER)11. SQL查询优化的首要目标是提高查询效率,减少查询所需的时间和资源。
以下哪个不是优化查询性能的常用方法?A. 使用索引B. 优化数据结构C. 添加冗余数据D. 使用分页查询12. 在进行SQL查询优化时,对查询语句进行规范化处理可以提高查询效率。
SQL优化:慎用标量子查询,改用leftjoin提升查询效率
SQL优化:慎⽤标量⼦查询,改⽤leftjoin提升查询效率⼀、项⽬实例问题1、问题背景 某个需求做了之后,注意到有个接⼝返回数据特别慢,特别是使⽤下⾯的 3 个字段排序时就直接卡死,肯定是 sql 性能写法问题,所以决定研究⼀下查看究竟。
其实需求挺简单,有⼏个字段排序,前端需要展⽰那些字段,然后之前的后端写的 sql 如下,仅提取主要问题点,其实就是需要拿到starCount、commentCount、totalReward ⽤来前端展⽰,⽽这三个字段呢,⼜需要从另外三个表⾥去分别计数,所以不考虑 sql 性能优化的话,就很容易想到了这种错误的写法。
k.tags,v.views,(select coalesce(count(rid),0) from table1 where aa ='kl'and rid = k.id) starCount,(select coalesce(count(id),0) from table2 where aa ='kl'and rid = k.id::varchar) commentCount,(select coalesce(count(id),0) from table3 where aa ='kl'and rid = k.id::varchar) totalRewardfrom table4 k left join table5 v on k.id = v.kl_id2、优化⽅案 主要优化后的 sql 如下:使⽤ left join 替代标量⼦查询k.tags,v.views,coalesce (s.count,0) starCount,coalesce (m.count,0) commentCount,coalesce (p.count,0) totalRewardfrom table4 k left join table5 v on k.id = v.kl_idleft join (select rid,count(rid) from table1 where aa ='kl'group by rid) s on k.id = s.ridleft join (select rid,count(rid) from table2 where aa ='kl'group by rid) m on m.rid = k.id::varcharleft join (select rid,count(rid) from table3 where aa ='kl'group by rid) p on p.rid = k.id::varcharorder by totalReward desc 优化前⽐如我有10万篇⽂章,那就要执⾏10万次(select coalesce(count(rid),0) from table1 where aa = 'kl' and rid = k.id) starCount。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
第一个案例: --产品名称 产品代码 分公司代码 分公司名称 中支代码 中支名称 四级机构代码 四级机构名称 银邮代理机构网点 银邮代理机构名称 网点代码(五级机构) 网点名称(五级机构) --失效保单件数 失效保单涉及销售金额 老年保单件数(投保人年龄在60岁以上) 老年保单涉及销售金额 select (select riskname from lis.lmrisk lr where lr.riskcode=a.riskcode ) 险种名称,riskcode 险种代码, substr(a.managecom,0,4) 分公司代码,(select name from lis.ldcom b where trim(b.comcode)=substr(a.managecom,0,4)) 分公司名称, substr(a.managecom,0,6) 中支代码,(select name from lis.ldcom b where trim(b.comcode)=substr(a.managecom,0,6)) 中支名称, substr(a.managecom,0,8) 四级代码,(select name from lis.ldcom b where trim(b.comcode)=trim(substr(a.managecom,0,8))) 四级名称, substr(a.agentcom,0,2) 总行,(select name from lis.lacom c where trim(c.agentcom)=substr(a.agentcom,0,2)) 总行名称, a.agentcom 网点代码,(select name from lis.lacom c where c.agentcom=a.agentcom) 网点名称, --substr(a.agentcom,0,10) 网点代码五级机构,(select name from lis.lacom c where trim(c.agentcom)=trim(substr(a.agentcom,0,10))) 网点名称五级机构, sum(case when exists (select 'x' from lis.lccontstate b where b.polno=a.polno and statetype='Available' and state='1') then 1 else 0 end) 失效保单件数, sum(case when exists (select 'x' from lis.lccontstate b where b.polno=a.polno and statetype='Available' and state='1') then prem else 0 end) 失效保单涉及销售金额, sum(case when(a.insuredappage>60 and appflag='1') then 1 else 0 end ) 老年保单件数, sum(case when (a.insuredappage>60 and appflag='1') then prem else 0 end ) 老年保单涉及销售金额 from lis.lcpol a where signdate<='2012-12-31' and riskcode in ('00639000', '00639100', '00613000', '00903000', '00640000', '00640100', '00608000', '00650200' ) and salechnl='3' group by riskcode,substr(a.managecom,0,4),substr(a.managecom,0,6),substr(a.managecom,0,8),substr(a.agentcom,0,2),a.agentcom 改造后: select /*+ orderd use_hash(a b) */ a.riskcode, substr(a.managecom,0,8),substr(a.agentcom,0,2), sum(case when b.rowid is not null then 1 else 0 end) 失效保单件数, sum(case when b.rowid is not null then prem else 0 end) 失效保单涉及销售金额, sum(case when(a.insuredappage>60 and appflag='1') then 1 else 0 end ) 老年保单件数, sum(case when(a.insuredappage>60 and appflag='1') then prem else 0 end ) 老年保单涉及销售金额 from lis.lcpol a ,lis.lccontstate b where b.polno(+)=a.polno and signdate<='2012-12-31' and riskcode in ('00639000', '00639100', '00613000', '00903000', '00640000', '00640100', '00608000', '00650200' ) and salechnl='3' and statetype(+)='Available' and state(+)='1' group by a.riskcode, substr(a.managecom,0,8),substr(a.agentcom,0,2) 第二个案例: select substr(p.managecom, 0, 4) 机构代码, (select name from lis.ldcom d where trim(d.comcode)=substr(p.managecom, 0, 4)) 机构名称, count(distinct AppntNo) 所属机构内符合条件客户数量 from lis.lcpol p where p.ContType = 1 and exists (select 'x' from lis.laagent la where la.agentcode||' ' = p.agentcode and la.branchtype in('1','4','6','7')) and p.signdate <= '2011-12-31' and p.insuyear>'1' and substr(p.managecom, 0, 6) not in ('862309','862302','862613','862611') and p.AppFlag ='1' and (case when (payintv='0' or (payintv='12' and p.payyears between 1 and 5) or p.riskcode in ('00888000','00902000','00903000','00904000','00905000','00890000','00907000','00909000','00910100','00912100','00913000','00652000','00658000','00673000','00674000','00678000') --(select 'x' from lis.lmrisksort a where risksorttype = '47' and a.riskcode=p.riskcode) ) then 0.1 when (payintv<>'0' and p.payyears between 6 and 10 ) then p.PayYears/10 when (payintv<>'0' and p.payyears>10) then 1 else 1 end )*p.prem>=2000 group by substr(p.managecom, 0, 4) union all select substr(p.managecom, 0, 6) 机构代码, (select name from lis.ldcom d where trim(d.comcode)=substr(p.managecom, 0, 6)) 机构名称, count(distinct AppntNo) 所属机构内符合条件客户数量 from lis.lcpol p where p.ContType = 1 and exists (select 'x' from lis.laagent la where la.agentcode||' ' = p.agentcode and la.branchtype in('1','4','6','7')) and p.signdate <= '2011-12-31' and p.insuyear>'1' and substr(p.managecom, 0, 6) in ('862309','862302','862613','862611') and p.AppFlag ='1' and (case when (payintv='0' or (payintv='12' and p.payyears between 1 and 5) or p.riskcode in ('00888000','00902000','00903000','00904000','00905000','00890000','00907000','00909000','00910100','00912100','00913000','00652000','00658000','00673000','00674000','00678000') --(select 'x' from lis.lmrisksort a where risksorttype = '47' and a.riskcode=p.riskcode)