首页 新闻 会员 周边

数据库中,where条件为什么查寻那么快?其算法或原理是什么?

1
悬赏园豆:50 [已解决问题] 解决于 2012-10-15 13:33

建立了索引的列,我明白通过索引能快速定位到指定数据。但是,像where后面可以是任何列(包括没列索引的列),但数据库为什么处理这些查询也那么快?

想这么问的原由是因为我在想,如果把一个百万级数据的表写到一个txt文本里,我可以根据源表的主键建立这个txt的索引,但想要像数据库那样,任意列都可以where的话,我就没思路了,除了遍历整个txt或为每个列都建索引的思路外,我就没思路了。所以求大神们指导。

幽灵~的主页 幽灵~ | 菜鸟二级 | 园豆:268
提问于:2012-09-07 12:06
< >
分享
最佳答案
2

在 SQL Server 中,页的大小为8 KB。这意味着SQL Server 数据库中每MB 有128 页。每页的开头
是一个96 B 的页头,用于存储有关页的系统信息。包括页码、页类型、页的可用空间,以及拥有该页
的对象的分配单元ID。不同类型的数据,存储在不同类型的页面里。

每一个文件都是一长串的bytes.SQL Server逻辑上(仅仅是逻辑上,不是物理上)把这个文件分成N多8K大小的块。这个块就是所谓的页。数据库文件第一个8K的块就是页#0,下一个8K的块就是页#1,依此类推。页是IO读取的最小单元,SQL Server每一个IO读写都涉及一个页,当然了,对于多个物理上连续的页,SQL Server也可以用一个IO全部完成。

    页不仅仅是IO读取的最小单位,也是所有权的最小单位。如果一页中包含了表A的一行数据,这页就只能存储表A的行数据了。或是一页中包含了索引B的条目,那这页也仅仅只能存储索引B的条目了。每页中除去存储数据之外,还存储一些页头信息以及行偏移以便SQL Server知道具体每一行在页中的存储位置。

SQL Server基于页之上做了另外一种逻辑分组,它将8个物理上连续的页分为一个区。正常情况下,和页一样,区也是所有权的最小单位,如果区中的一页属于表A或者表B,那么区中其它页也属于表A或者表B,但对于特别小的表或者索引就不适用了,对于很小的表和索引,一个区中的页可以属于两个以上的表。但对于大多数区来说,区都是所有权的基本单位。

    因此,对于表扫描来说,SQL Server并不是扫描所有的行,而是属于表的所有的页和区。SQL Server对于IO做的请求是8K或者64K字节的请求,甚至可能是并行读取表。这使得表扫描并不像想象的那么吓人,因为扫描是页为单位而不是每行都要做一个IO请求。

    以页和区作为单位不仅仅意味着减轻了表扫描的成本,还意味着,要从非聚集索引获益,查询请求的过滤条件要更具有选择性。
楼主这个问题概念涉及的太多了,数据库存储体系,SQL语法解析,索引实现,数据扫描等等。数据库中数据的存储方式 按页、块存储的,索引的作用也就像书的目录一样指向了存储的页码,这提高了检索速度。
文件系统的检索也可以有算法速度很快,楼主参考下:

全文检索引擎_Lucene

http://baike.baidu.com/view/371811.htm

收获园豆:50
acepro | 小虾三级 |园豆:1218 | 2012-09-07 14:20
其他回答(5)
0

where后面可以是任何列(包括没列索引的列)  这个想法应该不对吧。

文件跟数据库完全不是一个概念。

chenping2008 | 园豆:9836 (大侠五级) | 2012-09-07 13:09

先谢谢啊。

其实文件与数据库概念再不一样,至少存到硬盘里都是二进制。数据库是怎么存的数据?为什么一个where就那么快出数据?回答这两个问题也行。

支持(0) 反对(0) 幽灵~ | 园豆:268 (菜鸟二级) | 2012-09-07 13:45
0

其实把txt的内容读到datatable里再进行where搜索

jason2013 | 园豆:1998 (小虾三级) | 2012-09-07 13:15

如果这样的话,那也就不问了。

支持(0) 反对(0) 幽灵~ | 园豆:268 (菜鸟二级) | 2012-09-07 13:45
0

直接用StreamReader  ReadLine,从100W行txt中查找结果也才1秒多一点,没有任何优化。。。

向往-SONG | 园豆:4853 (老鸟四级) | 2012-09-07 13:32

看了你的我也做了一个测试,做了一个UTF-8的txt,10W行数据(没用100W),70多兆(这是我们项目用的真实数据,所以有代表性)。如果做空循环的话,确实一秒也用不了就循环完了。但加个小逻辑

if(line.IndexOf("xxxx")>-1)

    index++;

这样的话,就2秒多了。

还有,如果单是遍历的话,我这个文本真要是扩展到100W的话,就是700兆,光读硬盘一秒钟也就几十兆的读取量。

所以,在谢谢你的同时,我还是感觉数据库本身有更好的算法。

支持(0) 反对(0) 幽灵~ | 园豆:268 (菜鸟二级) | 2012-09-07 14:13

@幽灵~: 

数据库当然是有它的一套东西,插入数据的时候就已经做了处理,单纯的一个txt完全没经过加工没有组织的数据,直接去遍历当然慢了。

支持(0) 反对(0) 向往-SONG | 园豆:4853 (老鸟四级) | 2012-09-07 14:29
0

其实楼上的童鞋们说的很明白了楼主,数据库表当然不能和文本做比较了,两者的存储方式是完全不同的。数据库的存在就是为了快速存取和检索数据而设计的,其结构在设计上就是为了这种快速读取设计的。

你如果想快速读取你的文本,就只能改变他的存储方式的,比如在这个文本文件之外在建个和这个文本文件同步的索引文件。这样你就可以快速定位一条记录在源文件的位置了。如果想和数据库的速度相提并论那你就相当于在设计一个数据库了那个恐怕就不能你在一个项目了所能实现的了。

meil | 园豆:207 (菜鸟二级) | 2012-09-07 15:11
0

如果数据库处理查询不这么快的话,Oracle早破产了。

Launcher | 园豆:45045 (高人七级) | 2012-09-07 15:51
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册