数据库查询优化让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) 。


相关文章
|
14天前
|
SQL 数据库
数据库数据恢复—SQL Server数据库报错“错误823”的数据恢复案例
SQL Server附加数据库出现错误823,附加数据库失败。数据库没有备份,无法通过备份恢复数据库。 SQL Server数据库出现823错误的可能原因有:数据库物理页面损坏、数据库物理页面校验值损坏导致无法识别该页面、断电或者文件系统问题导致页面丢失。
82 12
数据库数据恢复—SQL Server数据库报错“错误823”的数据恢复案例
|
1天前
|
SQL 存储 移动开发
HTML5 Web SQL 数据库详解
Web SQL 数据库是 HTML5 中的一种本地存储技术,允许在浏览器中使用 SQL 语言操作本地数据,支持离线访问和事务处理,适用于缓存数据和小型应用。然而,其存储容量有限且仅部分现代浏览器支持,标准已不再积极维护,未来可能被 IndexedDB 和 localStorage 等技术取代。使用时需谨慎考虑兼容性和发展前景。
|
19天前
|
SQL 监控 关系型数据库
MySQL数据库中如何检查一条SQL语句是否被回滚
检查MySQL中的SQL语句是否被回滚需要综合使用日志分析、事务状态监控和事务控制语句。理解和应用这些工具和命令,可以有效地管理和验证数据库事务的执行情况,确保数据的一致性和系统的稳定性。此外,熟悉事务的ACID属性和正确设置事务隔离级别对于预防数据问题和解决事务冲突同样重要。
30 2
|
1月前
|
SQL 存储 关系型数据库
Hologres SQL 查询优化技巧
【9月更文第1天】随着大数据处理的需求日益增长,如何高效地进行数据查询和分析变得尤为重要。Hologres 是阿里云推出的一款实时数仓产品,它基于 PostgreSQL 构建,并针对在线分析处理(OLAP)场景进行了优化,支持实时数据写入与查询,能够实现毫秒级的查询响应。本文将探讨在使用 Hologres 时如何编写高效的 SQL 查询,并介绍一些特定于 Hologres 的优化技巧。
72 2
|
1月前
|
SQL 安全 数据库
基于SQL Server事务日志的数据库恢复技术及实战代码详解
基于事务日志的数据库恢复技术是SQL Server中一个非常强大的功能,它能够帮助数据库管理员在数据丢失或损坏的情况下,有效地恢复数据。通过定期备份数据库和事务日志,并在需要时按照正确的步骤恢复,可以最大限度地减少数据丢失的风险。需要注意的是,恢复数据是一个需要谨慎操作的过程,建议在执行恢复操作之前,详细了解相关的操作步骤和注意事项,以确保数据的安全和完整。
59 0
|
2月前
|
前端开发 C# 设计模式
“深度剖析WPF开发中的设计模式应用:以MVVM为核心,手把手教你重构代码结构,实现软件工程的最佳实践与高效协作”
【8月更文挑战第31天】设计模式是在软件工程中解决常见问题的成熟方案。在WPF开发中,合理应用如MVC、MVVM及工厂模式等能显著提升代码质量和可维护性。本文通过具体案例,详细解析了这些模式的实际应用,特别是MVVM模式如何通过分离UI逻辑与业务逻辑,实现视图与模型的松耦合,从而优化代码结构并提高开发效率。通过示例代码展示了从模型定义、视图模型管理到视图展示的全过程,帮助读者更好地理解并应用这些模式。
58 0
|
2月前
|
SQL 数据处理 数据库
|
2月前
|
Java 数据库连接 数据库
告别繁琐 SQL!Hibernate 入门指南带你轻松玩转 ORM,解锁高效数据库操作新姿势
【8月更文挑战第31天】Hibernate 是一款流行的 Java 持久层框架,简化了对象关系映射(ORM)过程,使开发者能以面向对象的方式进行数据持久化操作而无需直接编写 SQL 语句。本文提供 Hibernate 入门指南,介绍核心概念及示例代码,涵盖依赖引入、配置文件设置、实体类定义、工具类构建及基本 CRUD 操作。通过学习,你将掌握使用 Hibernate 简化数据持久化的技巧,为实际项目应用打下基础。
66 0
|
2月前
|
SQL 存储 监控
|
2月前
|
API Java 数据库连接
从平凡到卓越:Hibernate Criteria API 让你的数据库查询瞬间高大上,彻底告别复杂SQL!
【8月更文挑战第31天】构建复杂查询是数据库应用开发中的常见需求。Hibernate 的 Criteria API 以其强大和灵活的特点,允许开发者以面向对象的方式构建查询逻辑,同时具备 SQL 的表达力。本文将介绍 Criteria API 的基本用法并通过示例展示其实际应用。此 API 通过 API 构建查询条件而非直接编写查询语句,提高了代码的可读性和安全性。无论是简单的条件过滤还是复杂的分页和连接查询,Criteria API 均能胜任,有助于提升开发效率和应用的健壮性。
62 0
下一篇
无影云桌面