ExcelHome技术论坛

 找回密码
 免费注册

QQ登录

只需一步,快速开始

快捷登录

搜索
EH技术汇-专业的职场技能充电站 妙哉!函数段子手趣味讲函数 Excel服务器-会Excel,做管理系统 效率神器,一键搞定繁琐工作
HR薪酬管理数字化实战 Excel 2021函数公式学习大典 Excel数据透视表实战秘技 打造核心竞争力的职场宝典
让更多数据处理,一键完成 数据工作者的案头书 免费直播课集锦 ExcelHome出品 - VBA代码宝免费下载
用ChatGPT与VBA一键搞定Excel WPS表格从入门到精通 Excel VBA经典代码实践指南
查看: 10468|回复: 14

[分享] 数据库设计与性能优化问题

[复制链接]

TA的精华主题

TA的得分主题

发表于 2009-7-21 23:40 | 显示全部楼层 |阅读模式
很多朋友希望了解数据库设计与性能优化问题
我这里就copy点东东

数据库设计与性能 (SQL Server Compact Edition)

通过正确设计 SQL Server 数据库和发布,可以显著提高 SQL Server 2005 Compact Edition (SQL Server Compact Edition) 应用程序性能。下列各节概述了可以用来增强性能的方法。

使用非规范化数据库
规范化的数据库可防止数据存在功能相关性,以便轻松、高效地更新数据库。但是,查询数据库时可能需要联接许多表来组合信息。随着联接表数目的增多,查询运行时间会大大增加。因此,规范化的数据库并不一定是最佳的选择。如果数据库适当程度地不合规范,则可以减少必须联接在一起的表的数目,而不会使更新过程过于复杂。这通常是一个很好的折衷办法。

注意:  
通常,如果有相当多的查询需要联接五个或六个以上的表,则应考虑使用非规范化数据库。



此外,数据库还有一些其他非规范化类型。例如,假设某数据库有以下两个表:Orders 和 Order Details。Orders 表包含客户订单的相关信息。Order Details 表包含每个订单中的具体产品。假设您希望查询每个订单的总美元金额。首先,您需要确定每个产品的美元金额(数量 * 单价 – 适用的折扣)。随后,您还需要按订单汇总这些金额。查询如下所示:

SELECT "Order ID", SUM("Unit Price" * Quantity * (1.0 - Discount))

AS Total FROM "Order Details"

GROUP BY "Order ID"


Order ID Total

----------------------------------------

10000 108

10001 1363.15000915527

10002 731.800003051758

10003 498.180023193359

10004 3194.19999694824

10005 173.400009155273

10006 87.2000007629395

10007 1405

10008 1171

10009 1530

10010 470

... ...

(1078 rows affected)

此查询的计算量不小。如果订单较多,运行查询将会花费很长时间。另一种方法是在下订单时计算订单的美元金额,然后将该金额存储在 Orders 表内的某个列中。使用此方法,只需查询该预先计算列即可返回所需的信息:

SELECT "Order ID", "Order Total" AS Total FROM Orders

通过创建预先计算的列,您可以节省大量查询时间,但是使用此方法时需要在表中多维护一列。

采用可变长度列还是固定长度列
在设计表时,了解使用可变长度列和使用固定长度列各有哪些利弊是非常有用的。由于可变长度列仅占用存储实际值所需的空间,所以可减小数据库大小。而固定长度列始终会占用架构定义的最大空间,即使在实际值为空时也是如此。与固定长度列相比,可变长度列的缺点是一些操作的效率不高。例如,如果可变长度列开始时很小,而某 UPDATE 子句使其显著增大,则可能就要重新定位记录。此外,频繁的更新会导致数据页随着时间推移变得比较零碎。因此,在数据长度变化不大并且需要频繁进行更新时,建议使用固定长度列。

创建长度较小的行
页中可容纳的行数取决于各行的紧凑程度。如果行较小,则页中可以容纳更多的行。因此,对行较为紧凑的表执行的单磁盘操作可以检索更多的行,从而使操作更为有效。此外,存储引擎缓存中也可以包含更多的行,而这可能会提高命中率。使用紧凑的行还可以防止浪费数据页上的空间。使用较大的行时,通常就会有这种浪费情况。

试考虑下面的极端示例:如果记录大小稍大于数据页的一半,每个数据页就会浪费几乎一半的空间。一些数据库设计人员会选用宽表设计方案并将主机数据库架构移植到设备上。这并不是一种高效的设计方案。一种可能的方法是拆分那些最关键的表。假设您有一个表,其中某些列具有非常稳定的值,而其他列的值更改非常频繁。那么,将这个表拆分为两个表(一个表包含频繁引用的列,另一个表包含稳定的列)是很有意义的。通过创建两个表,即可拥有长度较小的行的所有优点。但缺点是需要使用联接来组合信息。

使用长度较小的键
索引是创建索引所基于的表的有序子集。使用索引,可以快速地在一定范围内进行查找并指定排序顺序。与较大的键相比,较小的索引键占用的空间更小,并且更为有效。因为主键经常作为其他表的外键引用,所以使用紧凑的主键十分有用。如果没有现成的紧凑主键,则可以改用实现形式为整数的标识列。

具有一个或少数几个键列的索引称为窄索引。具有许多键列的索引称为宽索引。宽索引的键长度通常较大。一个极端的索引示例是包括表中的所有列。通过创建这样的索引,可以有效地制作原始表的副本。不过,在数据库大小和查询性能方面,这种做法的效率都十分低下。

发布项目的类型和选项
在 SQL Server 2000 中创建发布时,创建的发布将包含标准的项目。对这些项目进行筛选时,将使用常规筛选。但是,如果您是在 SQL Server 2005 中创建发布,则可以为发布中的项目选择两个附加选项。这两个选项可以控制筛选以及发布服务器和订阅服务器之间的数据流,分别是:

仅限下载(只读)
有时,希望在智能设备上使用的数据可能只存储在查找表中。例如,您的用户可能需要在智能设备上浏览公司通讯簿,但是不得编辑和更改此类信息。“仅限下载”项目类型正适合这种情况。由于不在设备上存储元数据,因此使用此类型时占用的空间更小,可以降低同步过程中的网络通信流量。

明确分区
虽然您可以使用 SQL Server 2000 创建分区组,但是这在上载数据过程中会对性能造成负面影响,因为在每次上载时都必须计算分区 ID 映射。对于 SQL Server 2005 中明确分区的项目,所上载的更改仅映射到单个分区 ID。这样速度更快,但有以下几点限制:

项目中的每一行必须仅属于一个分区 ID。

每个项目只能发布到单个发布中。

订阅服务器不能插入不属于其分区 ID 的行。

使用明确分区的项目还会影响筛选。筛选时有以下限制:

订阅服务器不能更新筛选所涉及的列。

在联接筛选器层次结构中,常规项目不能是明确分区项目的父级。

对于子级是明确分区项目的联接筛选器,join_unique_key 的值必须设置为 1。

每个项目只能有一个子集或联接筛选器。具有子集筛选器时,项目可以是联接筛选器的父级,但不能是联接筛选器的子级

评分

1

查看全部评分

TA的精华主题

TA的得分主题

 楼主| 发表于 2009-7-21 23:41 | 显示全部楼层
查询性能优化 (SQL Server Compact Edition)

您可以通过优化所用查询来提高 SQL Server 2005 Compact Edition (SQL Server Compact Edition) 应用程序性能。下列各节概述了可以用来优化查询性能的方法。

优化索引
创建有用的索引是提高查询性能的最重要方法之一。有用的索引可帮助减少在查找数据时所需使用的磁盘 I/O 操作数和系统资源量。

若要创建有用的索引,您必须了解下列知识:数据的使用方式,查询的类型及其运行频率,以及查询处理器如何使用索引快速查找数据。

当选择要创建何种索引时,请检查您的关键查询,其性能将对用户体验产生极大的影响。需要创建专门辅助这些查询的索引。在添加索引后,重新运行查询以查看是否提高了性能。如果未提高,则删除索引。

与大多数性能优化方法一样,此方法也有一些缺点。例如,使用较多索引时,SELECT 查询的运行速度很可能会更快。但是,DML(INSERT、UPDATE 和 DELETE)操作的速度将显著减慢,因为对于每个操作都必须维护更多的索引。因此,如果您的查询主要包含 SELECT 语句,则使用较多的索引是非常有帮助的。如果您的应用程序需要执行许多 DML 操作,就有必要控制创建的索引数。

SQL Server Compact Edition 包括对显示计划的支持,显示计划可以帮助评估和优化查询。除了 SQL Server Compact Edition 使用的只是一部分运算符之外,SQL Server Compact Edition 使用与 SQL Server 2005 相同的显示计划架构。有关详细信息,请参阅位于 http://schemas.microsoft.com/sqlserver/2004/07/showplan/ 的 Microsoft 显示计划架构。

下面几节介绍有关创建有用索引的其他信息。

创建高选择性索引
对关键查询的 WHERE 子句中使用的列创建索引,通常会提高性能。但是,这取决于索引选择性的高低。选择性是指符合条件的行数与总行数之比。如果比率较低,索引就是高选择性的。它可以筛选掉大多数行,从而大大减小结果集的大小。因此,这样的索引就是要创建的有用索引。与之相比,选择性低的索引就没有那么有用。

唯一索引具有最高的选择性。只有一行可以匹配,这对只希望返回一行的查询是最有用的。例如,唯一 ID 列的索引可帮助您快速查找特定的行。

通过对 SQL Server Compact Edition 表运行 sp_show_statistics 存储过程,您可以评估索引的选择性。例如,若要评估两个列(“Customer ID”和“Ship Via”)的选择性,可以运行下列存储过程:

sp_show_statistics_steps 'orders', 'customer id';


RANGE_HI_KEY RANGE_ROWS EQ_ROWS DISTINCT_RANGE_ROWS

------------------------------------------------------------

ALFKI               0            7                   0

ANATR               0            4                   0

ANTON               0           13                   0

AROUT               0           14                   0

BERGS               0           23                   0

BLAUS               0            8                   0

BLONP               0           14                   0

BOLID               0            7                   0

BONAP               0           19                   0

BOTTM               0           20                   0

BSBEV               0           12                   0

CACTU               0            6                   0

CENTC               0            3                   0

CHOPS               0           12                   0

COMMI               0            5                   0

CONSH               0            4                   0

DRACD               0            9                   0

DUMON               0            8                   0

EASTC               0           13                   0

ERNSH               0           33                   0

(90 rows affected)



sp_show_statistics_steps 'orders', 'reference3';


RANGE_HI_KEY RANGE_ROWS EQ_ROWS DISTINCT_RANGE_ROWS

------------------------------------------------------------

1               0            320                   0

2               0            425                   0

3               0            333                   0

(3 rows affected)


结果表明“Customer ID”列的重复程度更低。这意味着其索引的选择性将比“Ship Via”列的索引的选择性要高。

有关使用这些存储过程的详细信息,请参阅 sp_show_statistics (SQL Server Compact Edition)、sp_show_statistics_steps (SQL Server Compact Edition) 和 sp_show_statistics_columns (SQL Server Compact Edition)。

创建多列索引
多列索引是单列索引的自然扩展。对于计算与预先指定的一组键列匹配的筛选表达式,多列索引是非常有用的。例如,组合索引 CREATE INDEX Idx_Emp_Name ON Employees ("Last Name" ASC, "First Name" ASC) 有助于计算下列查询:

... WHERE "Last Name" = 'Doe'

... WHERE "Last Name" = 'Doe' AND "First Name" = 'John'

... WHERE "First Name" = 'John' AND "Last Name" = 'Doe'

但是,它对下面的查询是没有用的:

... WHERE "First Name" = 'John'

在创建多列查询时,应该将选择性最高的列放在键中的最左端。这样,在匹配多个表达式时,就可以使索引的选择性更高。

避免对小表创建索引
小表是指内容只适合一个或几个数据页的表。因为进行表扫描通常效率更高,所以要避免对非常小的表创建索引。这会节省加载和处理索引页的开销。不对非常小的表创建索引,可以避免优化器选择此类索引。

SQL Server Compact Edition 按 4 Kb 一页来存储数据。使用以下公式可以计算出近似的页数,尽管实际的页数由于存储引擎开销的原因可能会稍微多一些。

<列的总大小(字节)> * <行数>

<页数> = -----------------------------------------------------------------

4096

例如,假设一个表的架构如下:

列名  类型(大小)  
订单 ID
INTEGER(4 字节)

产品 ID
INTEGER(4 字节)

单价
MONEY(8 字节)

数量
SMALLINT(2 字节)

折扣
REAL(4 字节)


此表包含 2820 行。按照公式,存储该表数据需要大约 16 页:

<页数> = ((4 + 4 + 8 + 2 + 4) * 2820) / 4096 = 15.15 页

选择要创建索引的对象
建议始终对主键创建索引。另外,对外键创建索引通常也非常有用。这是因为通常使用主键和外键来联接表。创建这些键的索引后,优化器可以使用效率更高的索引联接算法。如果您的查询使用其他列来联接表,由于相同的原因,对这些列创建索引通常也非常有用。

在创建主键和外键的约束后,SQL Server Compact Edition 将自动为其创建索引并在优化查询时加以利用。请记住使用较小的主键和外键。这样,联接的运行速度会更快。

与筛选子句一起使用索引
索引可以用于提高某些类型的筛选子句的计算速度。虽然所有筛选子句都会减小查询的最终结果集,但是某些筛选子句还可以帮助减小所需扫描的数据量。

搜索参数 (SARG) 可指定精确匹配、值的范围或由 AND 联接的两项或多项的连接,因此能够限制搜索范围。搜索参数采用以下格式之一:

列 运算符 <常量或变量>

<常量或变量> 运算符 列

SARG 运算符包括 =、>、<、>=、<=、IN、BETWEEN,有时还包括 LIKE(在进行前缀匹配时,如 LIKE 'John%')。SARG 可以包括由 AND 联接的多个条件。SARG 还可以是匹配特定值的查询,例如:

"Customer ID" = 'ANTON'

'Doe' = "Last Name"

SARG 也可以是匹配一定范围的值的查询,例如:

"Order Date" > '1/1/2002'

"Customer ID" > 'ABCDE' AND "Customer ID" < 'EDCBA'

"Customer ID" IN ('ANTON', 'AROUT')

不使用 SARG 运算符的表达式无法提高性能,因为 SQL Server Compact Edition 查询处理器必须评估所有行,以确定是否满足筛选子句。因此,对于不使用 SARG 运算符的表达式,索引是没有用的。非 SARG 运算符包括 NOT、<>、NOT EXISTS、NOT IN、NOT LIKE 和内部函数。

使用查询优化器
在确定基表的访问方法时,SQL Server Compact Edition 优化器将确定是否存在 SARG 子句的索引。如果存在索引,优化器将通过计算返回多少行来评估索引。然后,优化器会估计通过使用索引查找符合条件的行的开销。如果使用索引的开销比表扫描的开销低,优化器将选择索引访问。如果在 SARG 中使用索引的第一列或预先指定的一组列,且 SARG 指定了限制搜索范围的下限、上限或同时执行了这两者,则索引很可能是有用的。

了解响应时间与总时间
响应时间是查询返回第一条记录所用的时间。总时间是查询返回所有记录所用的时间。对于交互式应用程序,响应时间是很重要的,因为这决定了用户要等待多长时间,才能通过看到第一条返回记录确定查询正在处理中。对于批处理应用程序,总时间反映了总体吞吐量。您必须确定应用程序和查询的性能标准,然后才能相应地进行设计。

例如,假设查询返回 100 条记录,前五条记录用来填充一个列表。在此情况下,您不关心返回全部 100 条记录所用的时间。相反,您只希望查询快速返回前几条记录,以便填充列表。

可以执行许多查询操作,而无需存储中间结果。这些操作称为管道操作。管道操作的示例是映射、选择和联接。通过这些操作执行的查询可以立即返回结果。其他操作(如 SORT 和 GROUP-BY)需要使用所有输入信息,才可以将结果返回到父操作。这就是我们所说的要求具体化的操作。由于具体化的原因,通过这些操作执行的查询通常会有初始延迟。在此初始延迟之后,此类查询通常也可以很快地返回记录。

具有响应时间要求的查询应避免具体化。例如,与使用排序相比,使用索引执行 ORDER-BY 的响应时间更短。下一节将对此进行详细说明。

对 ORDER-BY/GROUP-BY/DISTINCT 列创建索引以缩短响应时间
ORDER-BY、GROUP-BY 和 DISTINCT 操作都是排序类型的操作。SQL Server Compact Edition 查询处理器使用两种方法进行排序。如果记录已经按索引进行排序,则处理器只使用索引。否则,处理器必须先使用临时工作表对记录进行排序。在 CPU 较慢并且内存较低的设备上,这样的预先排序会造成显著的初始延迟,因此,在响应时间比较重要时,应该避免预先排序。

在使用多列索引的情况下,为了使 ORDER-BY 或 GROUP-BY 处理特定索引,ORDER-BY 或 GROUP-BY 列必须与预先指定的一组索引列匹配,而且顺序要完全相同。例如,索引 CREATE INDEX Emp_Name ON Employees ("Last Name" ASC, "First Name" ASC) 有助于优化下列查询:

... ORDER BY / GROUP BY "Last Name" ...

... ORDER BY / GROUP BY "Last Name", "First Name" ...

但对下列查询,它并没有帮助:

... ORDER BY / GROUP BY "First Name" ...

... ORDER BY / GROUP BY "First Name", "Last Name" ...

为了使 DISTINCT 操作处理多列索引,映射列表必须与所有索引列匹配,尽管顺序不必完全相同。上面的索引有助于优化下列查询:

... DISTINCT "Last Name", "First Name" ...

... DISTINCT "First Name", "Last Name" ...

但对下列查询,它并没有帮助:

... DISTINCT "First Name" ...

... DISTINCT "Last Name" ...

注意:  
如果您的查询始终返回唯一行,请不要指定 DISTINCT 关键字,因为它只会增加开销。




重写子查询以使用 JOIN
有时可以重写子查询以使用 JOIN,从而提高性能。创建 JOIN 的好处是,可以按与查询所定义顺序不同的顺序评估表。使用子查询的好处是,通常不必扫描子查询中的所有行就可以计算子查询表达式。例如,EXISTS 子查询可以在找到第一个符合条件的行时就返回 TRUE。

注意:  
SQL Server Compact Edition 查询处理器始终会重写 IN 子查询以使用 JOIN。对包含 IN 子查询子句的查询,不必使用此方法。



例如,若要确定包含至少一个折扣率大于或等于 25% 的项的所有订单,可以使用下面的 EXISTS 子查询:

SELECT "Order ID" FROM Orders O

WHERE EXISTS (SELECT "Order ID"

FROM "Order Details" OD

WHERE O."Order ID" = OD."Order ID"

AND Discount >= 0.25)

您也可以使用 JOIN 对其进行重写:

SELECT DISTINCT O."Order ID" FROM Orders O INNER JOIN "Order Details"

OD ON O."Order ID" = OD."Order ID" WHERE Discount >= 0.25

使用 Outer JOIN 进行限制
OUTER JOIN 与 INNER JOIN 的处理方式是不同的:对于 INNER JOIN 表,优化器会尝试重新排列联接顺序,而对于 OUTER JOIN 表则不会。外部表(LEFT OUTER JOIN 中的左表和 RIGHT OUTER JOIN 中的右表)将首先访问,然后才会访问内部表。这一固定的联接顺序可能会导致执行计划不能达到最优。

注意:  
SQL Server Compact Edition 查询处理器假定 INNER JOIN 包括的列上有索引(由用户或数据库创建)。



使用参数化查询
如果应用程序运行的一系列查询仅有一些常量是不同的,则可以通过使用参数化查询来提高性能。例如,若要按不同的客户返回订单,可以运行下面的查询:

SELECT "Customer ID" FROM Orders WHERE "Order ID" = ?

通过只编译一次查询然后多次执行编译好的计划,参数化查询可以提供更好的性能。从编程上讲,必须始终保持包含缓存查询计划的命令对象。如果破坏以前的命令对象再创建新的命令对象,会破坏缓存的计划。这要求重新编译查询。如果必须交替运行多个参数化查询,则可以创建几个命令对象,每个命令对象都包含一个参数化查询的缓存执行计划。这样,就可以有效避免重新编译所有这些查询了。

仅在必要时进行查询
SQL Server Compact Edition 查询处理器是查询关系数据库中存储的数据的强大工具。但是,任何查询处理器都会造成一定程度的内部开销。在开始真正地执行计划之前,查询处理器必须编译、优化和生成执行计划。对于很快完成的简单查询,尤其是这样。因此,您自己执行查询有时可以大大提高性能。如果每一毫秒对您的关键组件都很重要,建议您考虑自己执行简单查询这一替代方法。对于复杂的大型查询,这种工作最好还是留给查询处理器去做。

例如,假设您希望查找按订单 ID 排列的一系列订单的客户 ID。有两种方法可以实现此操作。第一种方法是对于每一次查找都执行下列步骤:

打开 Orders 基表

使用特定的“Order ID”查找行

检索“Customer ID”

或者,对于每一次查找都发出以下查询:

SELECT "Customer ID" FROM Orders WHERE "Order ID" = <the specific order id>


与手动解决方案相比,基于查询的解决方案更简单但速度更慢,因为 SQL Server Compact Edition 查询处理器需要将 SQL 声明语句转换为与手动执行时相同的三个操作。随后,这三个步骤将按顺序执行。选用哪种方法将取决于在应用程序中简易性和性能哪方面更重要。

TA的精华主题

TA的得分主题

 楼主| 发表于 2009-7-21 23:44 | 显示全部楼层
[广告] VBA代码宝 - VBA编程加强工具 · VBA代码随查随用  · 内置多项VBA编程加强工具       ★ 免费下载 ★      ★使用手册
优化连接 (SQL Server Compact Edition)

使用 SQL Server 2005 Compact Edition,您可以在 SQL Server Compact Edition 数据库和 SQL Server 数据库之间同步数据。由于同步是通过 TCP/IP 执行的,因此各种网络和带宽都可支持它。

若要优化性能,则可以根据网络连接的带宽来修改设置。下表显示了由 SQL Server Compact Edition 支持的某些 TCP/IP 网络所使用的带宽:

带宽范围         网络类型
高        &#8226;        以太网或局域网 (LAN)
                &#8226;        使用 ActiveSync 的 USB 连接(仅设备)
中        &#8226;        无线 LAN 网络
低        &#8226;        移动网络

通过移动网络同步数据时,发送到服务器的请求(以及来自服务器的响应)均可超时。如果低带宽连接传输数据时需要占用较长时间,则会发生这种情况。由于超时将导致同步失败,因此需要指定更长的超时值。

但是,如果超时不是什么问题,请缩短超时值的设置,因为使用高带宽连接时如果服务器出现响应延迟的情况,则它更可能是由于服务器不响应导致的。因此,运行在台式机上并通过 LAN 连接到服务器的应用程序,以及通过使用 ActiveSync 连接来连接到服务器的设备,应当使用更短的超时值。

通过各种类型的网络连接到服务器的应用程序应当检测网络带宽,并设置合适的超时值:

同步超时属性
您可以设置合并复制和 RDA 编程对象的以下超时属性,以优化各种网络带宽上的同步。

ConnectionRetryTimeout
指定在已建立的连接中断之后要继续重试发送请求的时间(以秒计)。

ConnectTimeout
指定连接到服务器要等待的时间(以毫秒计)。

ReceiveTimeout
指定对服务器请求进行响应要等待的时间(以毫秒计)。

SendTimeout
指定向服务器发送请求要等待的时间(以毫秒计)。

超时优化
下表为根据网络带宽设置超时值提供了推荐设置:

属性         高带宽         中带宽         低带宽         默认值
ConnectionRetryTimeout (s)        30        60        120        120
ConnectTimeout (ms)        3000         6000        12000         无
ReceiveTimeout (ms)        1000         3000        6000         60000
SendTimeout (ms)        1000         3000        6000         无

TA的精华主题

TA的得分主题

 楼主| 发表于 2009-7-21 23:49 | 显示全部楼层
操作符优化


IN 操作符

用IN写出来的SQL的优点是比较容易写及清晰易懂,这比较适合现代软件开发的风格。
但是用IN的SQL性能总是比较低的,从ORACLE执行的步骤来分析用IN的SQL与不用IN的SQL有以下区别:

ORACLE试图将其转换成多个表的连接,如果转换不成功则先执行IN里面的子查询,再查询外层的表记录,如果转换成功则直接采用多个表的连接方式查询。由此可见用IN的SQL至少多了一个转换的过程。一般的SQL都可以转换成功,但对于含有分组统计等方面的SQL就不能转换了。
推荐方案:在业务密集的SQL当中尽量不采用IN操作符。


NOT IN操作符

此操作是强列推荐不使用的,因为它不能应用表的索引。
推荐方案:用NOT EXISTS 或(外连接+判断为空)方案代替


操作符(不等于)

不等于操作符是永远不会用到索引的,因此对它的处理只会产生全表扫描。
推荐方案:用其它相同功能的操作运算代替,如
a!=0 改为 a>0 or a<0
a!=’’ 改为 a>’’
IS NULL 或IS NOT NULL操作(判断字段是否为空)

判断字段是否为空一般是不会应用索引的,因为B树索引是不索引空值的。
推荐方案:
用其它相同功能的操作运算代替,如
a is not null 改为 a>0 或a>’’等。
不允许字段为空,而用一个缺省值代替空值,如业扩申请中状态字段不允许为空,缺省为申请。

建立位图索引(有分区的表不能建,位图索引比较难控制,如字段值太多索引会使性能下降,多人更新操作会增加数据块锁的现象)


> 及 操作符(大于或小于操作符)


大于或小于操作符一般情况下是不用调整的,因为它有索引就会采用索引查找,但有的情况下可以对它进行优化,如一个表有100万记录,一个数值型字段A, 30万记录的A=0,30万记录的A=1,39万记录的A=2,1万记录的A=3。那么执行A>2与A>=3的效果就有很大的区别了,因为 A>2时ORACLE会先找出为2的记录索引再进行比较,而A>=3时ORACLE则直接找到=3的记录索引。


LIKE操作符

LIKE操作符可以应用通配符查询,里面的通配符组合可能达到几乎是任意的查询,但是如果用得不好则会产生性能上的问题,如LIKE
‘%5400%’ 这种查询不会引用索引,而LIKE
‘X5400%’则会引用范围索引。一个实际例子:用YW_YHJBQK表中营业编号后面的户标识号可来查询营业编号
YY_BH LIKE ‘%5400%’ 这个条件会产生全表扫描,如果改成YY_BH LIKE ’X5400%’
OR YY_BH LIKE ’B5400%’ 则会利用YY_BH的索引进行两个范围的查询,性能肯定大大提高。


UNION操作符

UNION在进行表链接后会筛选掉重复的记录,所以在表链接后会对所产生的结果集进行排序运算,删除重复的记录再返回结果。实际大部分应用中是不会产生重复的记录,最常见的是过程表与历史表UNION。如:
select * from gc_dfys
union
select * from ls_jg_dfys
这个SQL在运行时先取出两个表的结果,再用排序空间进行排序删除重复的记录,最后返回结果集,如果表数据量大的话可能会导致用磁盘进行排序。
推荐方案:采用UNION ALL操作符替代UNION,因为UNION
ALL操作只是简单的将两个结果合并后就返回。
select * from gc_dfys
union all
select * from ls_jg_dfys


SQL书写的影响
同一功能同一性能不同写法SQL的影响

如一个SQL在A程序员写的为
Select * from zl_yhjbqk
B程序员写的为
Select * from dlyx.zl_yhjbqk(带表所有者的前缀)
C程序员写的为
Select * from DLYX.ZLYHJBQK(大写表名)
D程序员写的为
Select *   from DLYX.ZLYHJBQK(中间多了空格)


以上四个SQL在ORACLE分析整理之后产生的结果及执行的时间是一样的,但是从ORACLE共享内存SGA的原理,可以得出ORACLE对每个SQL
都会对其进行一次分析,并且占用共享内存,如果将SQL的字符串及格式写得完全相同则ORACLE只会分析一次,共享内存也只会留下一次的分析结果,这不仅可以减少分析SQL的时间,而且可以减少共享内存重复的信息,ORACLE也可以准确统计SQL的执行频率。


WHERE后面的条件顺序影响 - ORACLE采用自下而上的顺序解析WHERE子句,那些可以过滤掉最大数量记录的条件必须写在WHERE子句的末尾

WHERE子句后面的条件顺序对大数据量表的查询会产生直接的影响,如
Select * from zl_yhjbqk where dy_dj = '1KV以下' and
xh_bz=1
Select * from zl_yhjbqk where xh_bz=1   and dy_dj =
'1KV以下'
以上两个SQL中dy_dj(电压等级)及xh_bz(销户标志)两个字段都没进行索引,所以执行的时候都是全表扫描,第一条SQL的dy_dj
=
'1KV以下'条件在记录集内比率为99%,而xh_bz=1的比率只为0.5%,在进行第一条SQL的时候99%条记录都进行dy_dj及xh_bz的比较,而在进行第二条SQL的时候0.5%条记录都进行dy_dj及xh_bz的比较,以此可以得出第二条SQL的CPU占用率明显比第一条低。


查询表顺序的影响

在FROM后面的表中的列表顺序会对SQL执行性能影响,在没有索引及ORACLE没有对表进行统计分析的情况下ORACLE会按表出现的顺序进行链接,由此因为表的顺序不对会产生十分耗服务器资源的数据交叉。(注:如果对表进行了统计分析,ORACLE会自动先进小表的链接,再进行大表的链接)


SQL语句索引的利用

对操作符的优化(见上节)

对条件字段的一些优化
采用函数处理的字段不能利用索引,如:

substr(hbs_bh,1,4)=’5400’,优化处理:hbs_bh like ‘5400%’
trunc(sk_rq)=trunc(sysdate), 优化处理:
sk_rq>=trunc(sysdate) and sk_rq
进行了显式或隐式的运算的字段不能进行索引,如:

ss_df+20>50,优化处理:ss_df>30
‘X’||hbs_bh>’X5400021452’,优化处理:hbs_bh>’5400021542’
sk_rq+5=sysdate,优化处理:sk_rq=sysdate-5
hbs_bh=5401002554,优化处理:hbs_bh=’ 5401002554’,注:此条件对hbs_bh
进行隐式的to_number转换,因为hbs_bh字段是字符型。
条件内包括了多个本表的字段运算时不能进行索引,如:

ys_df>cx_df,无法进行优化
qc_bh||kh_bh=’5400250000’,优化处理:qc_bh=’5400’ and
kh_bh=’250000’


应用ORACLE的HINT(提示)处理



提示处理是在ORACLE产生的SQL分析执行路径不满意的情况下要用到的。它可以对SQL进行以下方面的提示
目标方面的提示:

COST(按成本优化)
RULE(按规则优化)
CHOOSE(缺省)(ORACLE自动选择成本或规则进行优化)
ALL_ROWS(所有的行尽快返回)
FIRST_ROWS(第一行数据尽快返回)
执行方法的提示:

USE_NL(使用NESTED LOOPS方式联合)
USE_MERGE(使用MERGE JOIN方式联合)
USE_HASH(使用HASH JOIN方式联合)
索引提示:

INDEX(TABLE INDEX)(使用提示的表索引进行查询)
其它高级提示(如并行处理等等)


ORACLE的提示功能是比较强的功能,也是比较复杂的应用,并且提示只是给ORACLE执行的一个建议,有时如果出于成本方面的考虑ORACLE也可能不会按提示进行。根据实践应用,一般不建议开发人员应用ORACLE提示,因为各个数据库及服务器性能情况不一样,很可能一个地方性能提升了,但另一个地方却下降了,ORACLE在SQL执行分析方面已经比较成熟,如果分析执行的路径不对首先应在数据库结构(主要是索引)、服务器当前性能(共享内存、磁盘文件碎片)、数据库对象(表、索引)统计信息是否正确这几方面分析。

TA的精华主题

TA的得分主题

发表于 2009-7-23 08:53 | 显示全部楼层
[广告] VBA代码宝 - VBA编程加强工具 · VBA代码随查随用  · 内置多项VBA编程加强工具       ★ 免费下载 ★      ★使用手册
好像还有下文,期待。

TA的精华主题

TA的得分主题

发表于 2009-7-25 20:26 | 显示全部楼层
规范化的数据库可防止数据存在功能相关性,以便轻松、高效地更新数据库。但是,查询数据库时可能需要联接许多表来组合信息。随着联接表数目的增多,查询运行时间会大大增加。因此,规范化的数据库并不一定是最佳的选择。如果数据库适当程度地不合规范,则可以减少必须联接在一起的表的数目,而不会使更新过程过于复杂。这通常是一个很好的折衷办法。

注意:  
通常,如果有相当多的查询需要联接五个或六个以上的表,则应考虑使用非规范化数据库。


初学,对更高深的问题缺少了解
只觉得,为了后续过程简便(比如为了查询方便、为了减少代码等)表可以不遵守规范化原则

TA的精华主题

TA的得分主题

发表于 2009-8-5 11:32 | 显示全部楼层

TA的精华主题

TA的得分主题

发表于 2009-11-19 23:02 | 显示全部楼层

TA的精华主题

TA的得分主题

发表于 2009-11-28 23:49 | 显示全部楼层
[广告] VBA代码宝 - VBA编程加强工具 · VBA代码随查随用  · 内置多项VBA编程加强工具       ★ 免费下载 ★      ★使用手册
学习一下!

TA的精华主题

TA的得分主题

发表于 2011-5-5 11:24 | 显示全部楼层
学习学习,对于深层次的理论问题,了解一些再设计系统时会好很多。
您需要登录后才可以回帖 登录 | 免费注册

本版积分规则

手机版|关于我们|联系我们|ExcelHome

GMT+8, 2024-11-17 12:48 , Processed in 0.036254 second(s), 10 queries , Gzip On, MemCache On.

Powered by Discuz! X3.4

© 1999-2023 Wooffice Inc.

沪公网安备 31011702000001号 沪ICP备11019229号-2

本论坛言论纯属发表者个人意见,任何违反国家相关法律的言论,本站将协助国家相关部门追究发言者责任!     本站特聘法律顾问:李志群律师

快速回复 返回顶部 返回列表