数据库查询优化让sql执行更快

简介: 人 们 在使用 SQL 时 往往会陷入一个 误 区,即太 关 注于所得的 结 果是否正确,而忽略了不同的 实现 方法之 间 可能存在的性能差异, 这种 性能差异在大型的或是 复杂 的数据 库环 境中(如 联 机事 务处 理 OLTP 或决策支持系 统 DSS )中表 现 得尤 为 明 显 。笔者在工作 实 践中 发现 ,不良的 SQL 往往来自于不恰当的索引 设计 、不充份的 连 接条件和不可 优 化的 where 子句。

人 们 在使用 SQL 时 往往会陷入一个 误 区,即太 关 注于所得的 结 果是否正确,而忽略了不同的 实现 方法之 间 可能存在的性能差异, 这种 性能差异在大型的或是 复杂 的数据 库环 境中(如 联 机事 务处 理 OLTP 或决策支持系 统 DSS )中表 现 得尤 为 明 显 。

笔者在工作 实 践中 发现 ,不良的 SQL 往往来自于不恰当的索引 设计 、不充份的 连 接条件和不可 优 化的 where 子句。

在 对 它 们进 行适当的 优 化后,其运行速度有了明 显 地提高!

下面我将从 这 三个方面分 别进 行 总结 :

为 了更直 观 地 说 明 问题 ,所有 实 例中的 SQL 运行 时间 均 经过测试 ,不超 过 1秒的均表示 为 ( < 1 秒)。 ----

测试环 境 :  主机: HP LH II----  主 频 : 330MHZ----  内存: 128 兆 ----

操作系 统 : Operserver5.0.4----

数据 库 : Sybase11.0.3

一、不合理的索引 设计 ----

例:表 record 有 620000 行, 试 看在不同的索引下,下面几个  SQL 的运行情况:

---- 1. 在 date 上建有一非个群集索引

select count(*) from record where date >'19991201' and date < '19991214'and amount >2000 (25秒)

select date ,sum(amount) from record group by date(55秒)

select count(*) from record where date >'19990901' and place in ('BJ','SH') (27秒)

----  分析: ----

date 上有大量的重 复值 ,在非群集索引下,数据在物理上随机存放在数据 页 上,在范 围查 找 时 ,必 须执 行一次表 扫 描才能找到 这 一范 围 内的全部行。

---- 2. 在 date 上的一个群集索引

select count(*) from record where date >'19991201' and date < '19991214' and amount >2000 (14秒)

select date,sum(amount) from record group by date(28秒)

select count(*) from record where date >'19990901' and place in ('BJ','SH')(14秒)

----  分析: ----  在群集索引下,数据在物理上按 顺 序在数据 页 上,重 复值 也排列在一起,因而在范 围查 找 时 ,可以先找到 这 个范 围 的起末点,且只在 这 个范 围 内 扫 描数据 页 ,避免了大范 围扫 描,提高了 查询 速度。

---- 3. 在 place , date , amount 上的 组 合索引

select count(*) from record where date >'19991201' and date < '19991214' and amount >2000 (26秒)

select date,sum(amount) from record group by date(27秒)

select count(*) from record where date >'19990901' and place in ('BJ, 'SH')(< 1秒)

----  分析: ----  这 是一个不很合理的 组 合索引,因 为 它的前 导 列是 place ,第一和第二条 SQL 没有引用 place ,因此也没有利用上索引;第三个 SQL 使用了 place ,且引用的所有列都包含在 组 合索引中,形成了索引覆盖,所以它的速度是非常快的。

---- 4. 在 date , place , amount 上的 组 合索引

select count(*) from record where date >'19991201' and date < '19991214' and amount >2000(< 1秒)

select date,sum(amount) from record group by date(11秒)

select count(*) from record where date >'19990901' and place in ('BJ','SH')(< 1秒)

----  分析: ----  这 是一个合理的 组 合索引。它将 date 作 为 前 导 列,使 每 个 SQL 都可以利用索引,并且在第一和第三个 SQL 中形成了索引覆盖,因而性能达到了最 优 。

---- 5. 总结 : ----

缺省情况下建立的索引是非群集索引,但有 时 它并不是最佳的;合理的索引 设计 要建立在 对 各 种查询 的分析和 预测 上。

一般来 说 :

① . 有大量重 复值 、且 经 常有范 围查询 ( between, >,<  , >=,< = )和 order by 、 group by 发 生的列,可考 虑 建立群集索引;

② . 经 常同 时 存取多列,且 每 列都含有重 复值 可考 虑 建立 组 合索引;

③ . 组 合索引要尽量使 关键查询 形成索引覆盖,其前 导 列一定是使用最 频 繁的列。

二、不充份的 连 接条件:

例:表 card 有 7896 行,在 card_no 上有一个非聚集索引,表 account 有 191122 行,在 account_no 上有一个非聚集索引, 试 看在不同的表 连 接条件下,两个 SQL 的 执 行情况:

select sum(a.amount) from account a,card b where a.card_no = b.card_no(20秒)

select sum(a.amount) from account a,card b where a.card_no = b.card_no and a.account_no=b.account_no(< 1秒)

----  分析: ----  在第一个 连 接条件下,最佳 查询 方案是将 account 作外 层 表, card 作内 层 表,利用 card 上的索引,其 I/O 次数可由以下公式估算 为 :

外 层 表 account 上的 22541 页 + (外 层 表 account 的 191122 行 * 内 层 表 card 上 对应 外 层 表第一行所要 查 找的 3 页 ) =595907 次 I/O

在第二个 连 接条件下,最佳 查询 方案是将 card 作外 层 表, account 作内 层 表,利用 account 上的索引,其 I/O 次数可由以下公式估算 为 :外 层 表 card 上的 1944 页 + (外 层 表 card 的 7896 行 * 内 层 表 account 上 对应 外 层 表 每 一行所要 查 找的 4 页 ) = 33528 次 I/O

可 见 ,只有充份的 连 接条件,真正的最佳方案才会被 执 行。

总结 :

1. 多表操作在被 实际执 行前, 查询优 化器会根据 连 接条件,列出几 组 可能的 连 接方案并从中找出系 统开销 最小的最佳方案。 连 接条件要充份考 虑带 有索引的表、行数多的表;内外表的 选择 可由公式:外 层 表中的匹配行数 * 内 层 表中 每 一次 查 找的次数确定,乘 积 最小 为 最佳方案。

2. 查 看 执 行方案的方法 --  用 set showplan on ,打 开 showplan 选项 ,就可以看到 连 接 顺 序、使用何 种 索引的信息;想看更 详细 的信息,需用 sa 角色 执 行 dbcc(3604,310,302) 。


相关文章
|
17天前
|
SQL Oracle 数据库
使用访问指导(SQL Access Advisor)优化数据库业务负载
本文介绍了Oracle的SQL访问指导(SQL Access Advisor)的应用场景及其使用方法。访问指导通过分析给定的工作负载,提供索引、物化视图和分区等方面的优化建议,帮助DBA提升数据库性能。具体步骤包括创建访问指导任务、创建工作负载、连接工作负载至访问指导、设置任务参数、运行访问指导、查看和应用优化建议。访问指导不仅针对单条SQL语句,还能综合考虑多条SQL语句的优化效果,为DBA提供全面的决策支持。
45 11
|
2月前
|
SQL 缓存 监控
大厂面试高频:4 大性能优化策略(数据库、SQL、JVM等)
本文详细解析了数据库、缓存、异步处理和Web性能优化四大策略,系统性能优化必知必备,大厂面试高频。关注【mikechen的互联网架构】,10年+BAT架构经验倾囊相授。
大厂面试高频:4 大性能优化策略(数据库、SQL、JVM等)
|
1月前
|
SQL 关系型数据库 MySQL
MySQL导入.sql文件后数据库乱码问题
本文分析了导入.sql文件后数据库备注出现乱码的原因,包括字符集不匹配、备注内容编码问题及MySQL版本或配置问题,并提供了详细的解决步骤,如检查和统一字符集设置、修改客户端连接方式、检查MySQL配置等,确保导入过程顺利。
|
30天前
|
SQL 监控 安全
SQL Servers审核提高数据库安全性
SQL Server审核是一种追踪和审查SQL Server上所有活动的机制,旨在检测潜在威胁和漏洞,监控服务器设置的更改。审核日志记录安全问题和数据泄露的详细信息,帮助管理员追踪数据库中的特定活动,确保数据安全和合规性。SQL Server审核分为服务器级和数据库级,涵盖登录、配置变更和数据操作等事件。审核工具如EventLog Analyzer提供实时监控和即时告警,帮助快速响应安全事件。
|
2月前
|
SQL 关系型数据库 MySQL
体验使用DAS实现数据库SQL优化,完成任务可得羊羔绒加厚坐垫!
本实验介绍如何通过数据库自治服务DAS对RDS MySQL高可用实例进行SQL优化,包含购买RDS实例并创建数据库、数据导入、生成并优化慢SQL、执行优化后的SQL语句等实验步骤。完成任务,即可领取羊羔绒加厚坐垫,限量500个,先到先得。
177 12
|
2月前
|
SQL 缓存 数据库
SQL慢查询优化策略
在数据库管理和应用开发中,SQL查询的性能优化至关重要。慢查询优化不仅可以提高应用的响应速度,还能降低服务器负载,提升用户体验。本文将详细介绍针对SQL慢查询的优化策略。
|
2月前
|
SQL 存储 BI
gbase 8a 数据库 SQL合并类优化——不同数据统计周期合并为一条SQL语句
gbase 8a 数据库 SQL合并类优化——不同数据统计周期合并为一条SQL语句
|
2月前
|
SQL 数据库
gbase 8a 数据库 SQL优化案例-关联顺序优化
gbase 8a 数据库 SQL优化案例-关联顺序优化
|
2月前
|
SQL 存储 Linux
从配置源到数据库初始化一步步教你在CentOS 7.9上安装SQL Server 2019
【11月更文挑战第16天】本文介绍了在 CentOS 7.9 上安装 SQL Server 2019 的详细步骤,包括配置系统源、安装 SQL Server 2019 软件包以及数据库初始化,确保 SQL Server 正常运行。
|
2月前
|
SQL 数据库 UED
SQL性能提升秘籍:5步优化法与10个实战案例
在数据库管理和应用开发中,SQL查询的性能优化至关重要。高效的SQL查询不仅可以提高应用的响应速度,还能降低服务器负载,提升用户体验。本文将分享SQL优化的五大步骤和十个实战案例,帮助构建高效、稳定的数据库应用。
81 3