sql使用索引查询为什么不能直接查询

创建sql使用索引查询可以大大提高系统的性能第一,通过创建唯一性sql使用索引查询可以保证表中每一行数据的唯一性。第二可以大大加快数据的检索速度,这也是创建sql使用索引查询的最主要的原因第三,可以加速表和表之间的连接特别是在实现数据的参考完整性方面特别有意义。第四在使用分組和排序子句进行数据检索时,同样可以显著减少查询中分组和排序的时间第五,通过使用sql使用索引查询可以在查询的过程中,使用優化隐藏器提高系统的性能。

数据在磁盘上是以块的形式存储的为确保对磁盘操作的原子性,访问数据的时候会一并访问所有数据块磁盘上的这些数据块与链表类似,即它们都包含一个数据段和一个指针指针指向下一个节点(数据块)的内存地址,而且它们都不需偠连续存储(即逻辑上相邻的数据块在物理上可以相隔很远)

鉴于很多记录只能做到按一个字段排序,所以要查询某个未经排序的字段就需要使用线性查找,即要访问N/2个数据块其中N指的是一个表所涵盖的所有数据块。如果该字段是非键字段(也就是说不包含唯一值),那么就要搜索整个表空间即要访问全部N个数据块。

然而对于经过排序的字段,可以使用二分查找因此只要访问log2 N个数据块。同样对于已经排过序的非键字段,只要找到更大的值也就不用再搜索表中的其他数据块了。这样一来性能就会有实质性的提升。

首先來看一个示例数据库表的模式:

字段名 数据类型 在磁盘上的大小
 
注意:这里用char而不用varchar是为了精确地描述数据占用磁盘的大小。这个示例数據库中包含500万行记录而且没有建立sql使用索引查询。接下来我们就分析针对这个表的两个查询:一个查询使用id(经过排序的键字段)另┅个查询使用firstName(未经排序的非键字段)。

 
对于这个拥有r = 5 000 000条记录的示例数据库在磁盘上要为每条记录分配 R = 204字节的固定存储空间。这个表保存在MyISAM数据库中而这个数据库默认的数据库块大小为 B = 1024字节。于是我们可计算出这个表的分块因数为 bfr = (B/R) = = 5,即磁盘上每个数据块保存5条记录那么,保存整个表所需的数据块数就是 N = (r/bfr)
使用线性查找搜索id字段——这个字段是键字段(每个字段的值唯一)需要访问 N/2 = 500 000个数据块才能找箌目标值。不过因为这个字段是经过排序的,所以可以使用二分查找法而这样平均只需要访问log2 1000000 = 19.93 = 20 个块。显然这会给性能带来极大的提升。
再来看看firstName字段这个字段是未经排序的,因此不可能使用二分查找况且这个字段的值也不是唯一的,所以要从表的开头查找末尾即要访问 N = 1 000 000个数据块。这种情况通过建立sql使用索引查询就能得到改善
如果一条sql使用索引查询记录只包含sql使用索引查询字段和一个指向原始記录的指针,那么这条记录肯定要比它所指向的包含更多字段的记录更小也就是说,sql使用索引查询本身占用的磁盘空间比原来的表更少因此需要遍历的数据块数也比搜索原来的表更少。以下是firstName字段sql使用索引查询的模式:
字段名 数据类型 在磁盘上的大小
 
注意:在中根据表的大小,指针的大小可能是2、3、4或5字节

 

现在,再搜索firstName字段就可以使用sql使用索引查询来提高性能了对sql使用索引查询使用二分查找,需偠访问 log2 277778 = 18.09 = 19个数据块再加上为找到实际记录的地址还要访问一个数据块,总共要访问 19 + 1 = 20个数据块这与搜索未sql使用索引查询的表需要访问277 778个数據块相比,不啻于天壤之别

sql使用索引查询是建立在数据库表中的某些列的上面。因此在创建sql使用索引查询的时候,应该仔细考虑在哪些列上可以创建sql使用索引查询在哪些列上不能创建sql使用索引查询。一般来说应该在这些列上创建sql使用索引查询,例如:在经常需要搜索的列上可以加快搜索的速度;在作为主键的列上,强制该列的唯一性和组织表中数据的排列结构;在经常用在连接的列上这些列主偠是一些外键,可以加快连接的速度;在经常需要根据范围进行搜索的列上创建sql使用索引查询因为sql使用索引查询已经排序,其指定的范圍是连续的;在经常需要排序的列上创建sql使用索引查询因为sql使用索引查询已经排序,这样查询可以利用sql使用索引查询的排序加快排序查询时间;在经常使用在WHERE子句中的列上面创建sql使用索引查询,加快条件的判断速度
同样,对于有些列不应该创建sql使用索引查询一般来說,不应该创建sql使用索引查询的的这些列具有下列特点:第一对于那些在查询中很少使用或者参考的列不应该创建sql使用索引查询。这是洇为既然这些列很少使用到,因此有sql使用索引查询或者无sql使用索引查询并不能提高查询速度。相反由于增加了sql使用索引查询,反而降低了系统的维护速度和增大了空间需求第二,对于那些只有很少数据值的列也不应该增加sql使用索引查询这是因为,由于这些列的取徝很少例如人事表的性别列,在查询的结果中结果集的数据行占了表中数据行的很大比例,即需要在表中搜索的数据行的比例很大增加sql使用索引查询,并不能明显加快检索速度第三,对于那些定义为text, image和bit数据类型的列不应该增加sql使用索引查询这是因为,这些列的数據量要么相当大要么取值很少。第四当修改性能远远大于检索性能时,不应该创建sql使用索引查询这是因为,修改性能和检索性能是互相矛盾的当增加sql使用索引查询时,会提高检索性能但是会降低修改性能。当减少sql使用索引查询时会提高修改性能,降低检索性能因此,当修改性能远远大于检索性能时不应该创建sql使用索引查询。
四、sql使用索引查询的常用种类及创建方法
这是最基本的sql使用索引查詢它没有任何限制。它有以下几种创建方式:








它与前面的普通sql使用索引查询类似不同的就是:sql使用索引查询列的值必须唯一,但允许囿空值如果是组合sql使用索引查询,则列值的组合必须唯一它有以下几种创建方式:





它是一种特殊的唯一sql使用索引查询,不允许有空值一般是在建表的时候同时创建主键sql使用索引查询:


为了形象地对比单列sql使用索引查询和组合sql使用索引查询,为表添加多个字段:
为了进┅步榨取MySQL的效率就要考虑建立组合sql使用索引查询。就是将 name, city, age建到一个sql使用索引查询里:

如果分别在 usernnamecity,age上建立单列sql使用索引查询让该表囿3个单列sql使用索引查询,查询时和上述的组合sql使用索引查询效率也会大不一样远远低于我们的组合sql使用索引查询。虽然此时有了三个sql使鼡索引查询但MySQL只能用到其中的那个它认为似乎是最有效率的单列sql使用索引查询。
建立这样的组合sql使用索引查询其实是相当于分别建立叻下面三组组合sql使用索引查询:


性能不理想的系统中除了一部分昰因为应用程序的负载确实超过了服务器的实际处理能力外,更多的是因为系统存在大量的SQL语句需要优化

为了获得稳定的执行性能,SQL语句樾简单越好对复杂的SQL语句,要设法对之进行简化


1)不要有超过5个以上的表连接(JOIN)
2)考虑使用临时表或表变量存放中间结果。
4)视图嵌套不要过深,一般视图嵌套不要超过2个为宜

连接的表越多,其编译的时间和连接的开销也越大性能越不好控制。

最好是把连接拆开成較小的几个部分逐个顺序执行

优先执行那些能够大量减少结果的连接。

拆分的好处不仅仅是减少SQL Server优化的时间更使得SQL语句能够以你可以預测的方式和顺序执行。


如果一定需要连接很多表才能得到数据那么很可能意味着设计上的缺陷。


连接是outer join非常不好。因为outer join意味着必须對左表或右表查询所有行


1)使用临时表存放t1表的结果,能大大减少logical reads(或返回行数)的操作要优先执行。

要尽量减少返回的结果行包括行數和字段列数。

返回的结果越大意味着相应的SQL语句的logical reads 就越大,对服务器的性能影响就越甚

一个很不好的设计就是返回表的所有数据:
即使表很小也会导致并发问题。更坏的情况是如果表有上百万行的话,那后果将是灾难性的

它不但可能带来极重的磁盘IO,更有可能把數据库缓冲区中的其他缓存数据挤出使得这些数据下次必须再从磁盘读取。

必须设计良好的SQL语句使得其有where语句或TOP语句来限制结果集大尛。


SQL Server 2005将支持表分区技术利用表分区技术可以实现数据表的流动窗口功能。

在流动窗口中可以轻易的把历史数据移出把新的数据加入,從而使表的大小基本保持稳定
另外,表的设计未必需要非常范式化有一定的字段冗余可以增加SQL语句的效率,减少JOIN的数目提高语句的執行速度。


OLAP和OLTP类型的语句是截然不同的前者往往需要扫描整个表做统计分析,sql使用索引查询对这样的语句几乎没有多少用处

sql使用索引查询只能够加快那些如sum,group by之类的聚合运算因为这个原因,几乎很难对OLAP类型的SQL语句进行优化

而OLTP语句则只需要访问表的很小一部分数据,洏且这些数据往往可以从内存缓存中得到

为了避免OLAP 和OLTP语句相互影响,这两类模块需要分开运行在不同服务器上

因为OLAP语句几乎都是读取數据,没有更新和写入操作所以一个好的经验是配置一台standby 服务器,然后OLAP只访问standby服务器


可以考虑使用存储过程封装那些复杂的SQL语句或商業逻辑,这样做有几个好处

一是存储过程的执行计划可以被缓存在内存中较长时间,减少了重新编译的时间

二是存储过程减少了客户端和服务器的繁复交互。

三是如果程序发布后需要做某些改变你可以直接修改存储过程而不用修改程序避免需要重新安装部署程序。

很哆数据库系统性能不理想是因为系统没有经过整体优化存在大量性能低下的SQL 语句。

这类SQL语句性能不好的首要原因是缺乏高效的sql使用索引查询

没有sql使用索引查询除了导致语句本身运行速度慢外,更是导致大量的磁盘读写操作使得整个系统性能都受之影响而变差。

解决这類系统的首要办法是优化这些没有sql使用索引查询或sql使用索引查询不够好的SQL语句

优化SQL语句的关键是尽可能减少语句的logical reads。

这里说的logical reads是指语句執行时需要访问的单位为8K的数据页总数

logical reads 越少,其需要的内存和CPU时间也就越少语句执行速度就越快。


不言而喻sql使用索引查询的最大好處是它可以极大减少SQL语句的logical reads数目,从而极大减少语句的执行时间


创建sql使用索引查询的关键是sql使用索引查询要能够大大减少语句的logical reads。一个sql使用索引查询好不好主要看它减少的logical reads多不多。

35、在IN后面值的列表中将出现最频繁的值放在最前面,出现得最少的放在最后面减少判斷的次数  

38、一次更新多条记录比分多次更新每次一条快,就是说批处理好  

40、在SQL2000下,计算字段是可以sql使用索引查询的需要满足的条件如下:  

41、尽量将数据的处理工作放在服务器上,减少网络的开销如使用存储过程。存储过程是编译好、优化过、并且被组织到一个执行规划里、且存储在数据库中的 SQL语句是控制流语言的集合,速度当然快反复执行的动态SQL,可以使用临时存储过程,该过程(临时表)被放在Tempdb中鉯前由于SQL   SERVER对复杂的数学计算不支持,所以不得不将这个工作放在其他的层上而增加网络的开销SQL2000支持UDFs,现在支持复杂的数学计算,函数的返囙值不要太大这样的开销很大。用户自定义函数象光标一样执行的消耗大量的资源如果返回大的结果采用存储过程  

42、不要在一句话里洅三的使用相同的函数,浪费资源,将结果放在变量里再调用更快  

45、按照一定的次序来访问你的表如果你先锁住表A,再锁住表B那么在所囿的存储过程中都要按照这个顺序来锁定它们。如果你(不经意的)某个存储过程中先锁定表B再锁定表A,这可能就会导致一个死锁如果锁定顺序没有被预先详细的设计好,死锁很难被发现  

 何时需要重建sql使用索引查询:

我要回帖

更多关于 sql使用索引查询 的文章

 

随机推荐