
1应尽量避免在 where 子句中对字段进行 null 值判断,否则将导致引擎放弃使用索引而进行全表扫描,如:
select id from t where num is null
可以在num上设置默认值0,确保表中num列没有null值,然后这样查询:
select id from t where num=0
2应尽量避免在 where 子句中使用!=或<> *** 作符,否则将引擎放弃使用索引而进行全表扫描。优化器将无法通过索引来确定将要命中的行数,因此需要搜索该表的所有行。
3应尽量避免在 where 子句中使用 or 来连接条件,否则将导致引擎放弃使用索引而进行全表扫描,如:
select id from t where num=10 or num=20
可以这样查询:
select id from t where num=10
union all
select id from t where num=20
4in 和 not in 也要慎用,因为IN会使系统无法使用索引,而只能直接搜索表中的数据。如:
select id from t where num in(1,2,3)
对于连续的数值,能用 between 就不要用 in 了:
select id from t where num between 1 and 3
5尽量避免在索引过的字符数据中,使用非打头字母搜索。这也使得引擎无法利用索引。
见如下例子:
SELECT FROM T1 WHERE NAME LIKE ‘%L%’
SELECT FROM T1 WHERE SUBSTING(NAME,2,1)=’L’
SELECT FROM T1 WHERE NAME LIKE ‘L%’
即使NAME字段建有索引,前两个查询依然无法利用索引完成加快 *** 作,引擎不得不对全表所有数据逐条 *** 作来完成任务。而第三个查询能够使用索引来加快 *** 作。
6必要时强制查询优化器使用某个索引,如在 where 子句中使用参数,也会导致全表扫描。因为SQL只有在运行时才会解析局部变量,但优化程序不能将访问计划的选择推迟到运行时;它必须在编译时进行选择。然而,如果在编译时建立访问计划,变量的值还是未知的,因而无法作为索引选择的输入项。如下面语句将进行全表扫描:
select id from t where num=@num
可以改为强制查询使用索引:
select id from t with(index(索引名)) where num=@num
7应尽量避免在 where 子句中对字段进行表达式 *** 作,这将导致引擎放弃使用索引而进行全表扫描。如:
SELECT FROM T1 WHERE F1/2=100
应改为:
SELECT FROM T1 WHERE F1=1002
SELECT FROM RECORD WHERE SUBSTRING(CARD_NO,1,4)=’5378’
应改为:
SELECT FROM RECORD WHERE CARD_NO LIKE ‘5378%’
SELECT member_number, first_name, last_name FROM members
WHERE DATEDIFF(yy,datofbirth,GETDATE()) > 21
应改为:
SELECT member_number, first_name, last_name FROM members
WHERE dateofbirth < DATEADD(yy,-21,GETDATE())
即:任何对列的 *** 作都将导致表扫描,它包括数据库函数、计算表达式等等,查询时要尽可能将 *** 作移至等号右边。
8应尽量避免在where子句中对字段进行函数 *** 作,这将导致引擎放弃使用索引而进行全表扫描。如:
select id from t where substring(name,1,3)='abc'--name以abc开头的id
select id from t where datediff(day,createdate,'2005-11-30')=0--‘2005-11-30’生成的id
应改为:
select id from t where name like 'abc%'
select id from t where createdate>='2005-11-30' and createdate<'2005-12-1'
9不要在 where 子句中的“=”左边进行函数、算术运算或其他表达式运算,否则系统将可能无法正确使用索引。
10在使用索引字段作为条件时,如果该索引是复合索引,那么必须使用到该索引中的第一个字段作为条件时才能保证系统使用该索引,否则该索引将不会被使用,并且应尽可能的让字段顺序与索引顺序相一致。
11很多时候用 exists是一个好的选择:
elect num from a where num in(select num from b)
用下面的语句替换:
select num from a where exists(select 1 from b where num=anum)
SELECT SUM(T1C1)FROM T1 WHERE(
(SELECT COUNT()FROM T2 WHERE T2C2=T1C2>0)
SELECT SUM(T1C1) FROM T1WHERE EXISTS(
SELECT FROM T2 WHERE T2C2=T1C2)
两者产生相同的结果,但是后者的效率显然要高于前者。因为后者不会产生大量锁定的表扫描或是索引扫描。
总结优化如下:
1、主键就是聚集索引
2、只要建立索引就能显著提高查询速度
3、把所有需要提高查询速度的字段都加进聚集索引,以提高查询速度
(四)其他书上没有的索引使用经验总结
1、用聚合索引比用不是聚合索引的主键速度快
2、用聚合索引比用一般的主键作order by时速度快,特别是在小数据量情况下
3、使用聚合索引内的时间段,搜索时间会按数据占整个数据表的百分比成比例减少,而无论聚合索引使用了多少个
4 、日期列不会因为有分秒的输入而减慢查询速度
(五)其他注意事项
1 不要索引常用的小型表
2 不要把社会保障号码(SSN)或身份z号码(ID)选作键
3 不要用用户的键
4 不要索引 memo/notes 字段和不要索引大型文本字段(许多字符)
5 使用系统生成的主键
二、改善SQL语句
1、Like语句是否属于SARG取决于所使用的通配符的类型
2、or 会引起全表扫描
3、非 *** 作符、函数引起的不满足SARG形式的语句
4、IN 的作用相当与OR
5、尽量少用NOT
6、exists 和 in 的执行效率是一样的
7、用函数charindex()和前面加通配符%的LIKE执行效率一样
8、union并不绝对比or的执行效率高
9、字段提取要按照“需多少、提多少”的原则,避免“select ”
10、count()不比count(字段)慢
11、order by按聚集索引列排序效率最高
12、高效的TOP
表设计可以采取拆分表的方式
纵向拆分表:根据字段拆分为多个表,每个表都有关联字段,可以将他们关联起来
(例如:订单表,几个根据字段拆分的表中都有1个订单号字段)
横向拆分表:不知道你具体什么数据,假定其中有时间字段,根据时间来拆分
(例如:1年有12个月,1个月的数据放入一个表中)
1 SQL优化的原则是:将一次 *** 作需要读取的BLOCK数减到最低,即在最短的时间达到最大的数据吞吐量。 调整不良SQL通常可以从以下几点切入: 检查不良的SQL,考虑其写法是否还有可优化内容 检查子查询 考虑SQL子查询是否可以用简单连接的方式进行重新书写 检查优化索引的使用 考虑数据库的优化器 2 避免出现SELECT FROM table 语句,要明确查出的字段。 3 在一个SQL语句中,如果一个where条件过滤的数据库记录越多,定位越准确,则该where条件越应该前移。 4 查询时尽可能使用索引覆盖。即对SELECT的字段建立复合索引,这样查询时只进行索引扫描,不读取数据块。 5 在判断有无符合条件的记录时建议不要用SELECT COUNT ()和select top 1 语句。 6 使用内层限定原则,在拼写SQL语句时,将查询条件分解、分类,并尽量在SQL语句的最里层进行限定,以减少数据的处理量。 7 应绝对避免在order by子句中使用表达式。 8 如果需要从关联表读数据,关联的表一般不要超过7个。 9 小心使用 IN 和 OR,需要注意In集合中的数据量。建议集合中的数据不超过200个。 10 <> 用 < 、 > 代替,>用>=代替,<用<=代替,这样可以有效的利用索引。 11 在查询时尽量减少对多余数据的读取包括多余的列与多余的行。 12 对于复合索引要注意,例如在建立复合索引时列的顺序是F1,F2,F3,则在where或order by子句中这些字段出现的顺序要与建立索引时的字段顺序一致,且必须包含第一列。只能是F1或F1,F2或F1,F2,F3。否则不会用到该索引。 13 多表关联查询时,写法必须遵循以下原则,这样做有利于建立索引,提高查询效率。格式如下select sum(table1je) from table1 table1, table2 table2, table3 table3 where (table1的等值条件(=)) and (table1的非等值条件) and (table2与table1的关联条件) and (table2的等值条件) and (table2的非等值条件) and (table3与table2的关联条件) and (table3的等值条件) and (table3的非等值条件)。 注:关于多表查询时from 后面表的出现顺序对效率的影响还有待研究。 14 子查询问题。对于能用连接方式或者视图方式实现的功能,不要用子查询。例如:select name from customer where customer_id in ( select customer_id from order where money>1000)。应该用如下语句代替:select name from customer inner join order on customercustomer_id=ordercustomer_id where ordermoney>100。 15 在WHERE 子句中,避免对列的四则运算,特别是where 条件的左边,严禁使用运算与函数对列进行处理。比如有些地方 substring 可以用like代替。 16 如果在语句中有not in(in) *** 作,应考虑用not exists(exists)来重写,最好的办法是使用外连接实现。 17 对一个业务过程的处理,应该使事物的开始与结束之间的时间间隔越短越好,原则上做到数据库的读 *** 作在前面完成,数据库写 *** 作在后面完成,避免交叉。 18 请小心不要对过多的列使用列函数和order by,group by等,谨慎使用disti软件开发t。 19 用union all 代替 union,数据库执行union *** 作,首先先分别执行union两端的查询,将其放在临时表中,然后在对其进行排序,过滤重复的记录。 当已知的业务逻辑决定query A和query B中不会有重复记录时,应该用union all代替union,以提高查询效率。数据更新的效率 1 在一个事物中,对同一个表的多个insert语句应该集中在一起执行。 2 在一个业务过程中,尽量的使insert,update,delete语句在业务结束前执行,以减少死锁的可能性。 数据库物理规划的效率 为了避免I/O的冲突,我们在设计数据库物理规划时应该遵循几条基本的原则(以ORACLE举例): table和index分离:table和index应该分别放在不同的tablespace中。 Rollback Segment的分离:Rollback Segment应该放在独立的Tablespace中。 System Tablespace的分离:System Tablespace中不允许放置任何用户的object。(mssql中primary filegroup中不允许放置任何用户的object) Temp Tablesace的分离:建立单独的Temp Tablespace,并为每个user指定default Temp Tablespace 避免碎片:但segment中出现大量的碎片时,会导致读数据时需要访问的block数量的增加。对经常发生DML *** 作的segemeng来说,碎片是不能完全避免的。所以,我们应该将经常做DML *** 作的表和很少发生变化的表分离在不同的Tablespace中。 当我们遵循了以上原则后,仍然发现有I/O冲突存在,我们可以用数据分离的方法来解决。 连接Table的分离:在实际应用中经常做连接查询的Table,可以将其分离在不同的Taclespace中,以减少I/O冲突。 使用分区:对数据量很大的Table和Index使用分区,放在不同的Tablespace中。 在实际的物理存储中,建议使用RAID。日志文件应放在单独的磁盘中。
以上就是关于数据库的多表大数据查询应如何优化全部的内容,包括:数据库的多表大数据查询应如何优化、如何优化数据库、Oracle数据库大数据量表如何优化等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)