海量数据库查询语句

前端之家收集整理的这篇文章主要介绍了海量数据库查询语句前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

以下代码说明了我们实例中数据库的“红头文件”一表的部分数据结构:
<DIV style="BORDER-RIGHT: #8a8a8a 1px solid; PADDING-RIGHT: 6px; BORDER-TOP: #8a8a8a 1px solid; PADDING-LEFT: 6px; FONT-SIZE: 12px; PADDING-BOTTOM: 6px; MARGIN: 1px; OVERFLOW: auto; BORDER-LEFT: #8a8a8a 1px solid; PADDING-TOP: 6px; BORDER-BOTTOM: #8a8a8a 1px solid; FONT-FAMILY: Courier New; BACKGROUND-COLOR: #eeeeee"><SPAN style="COLOR: #0000ff">CREATE
<SPAN style="COLOR: #0000ff">TABLE[dbo].[TGongwen](<SPAN style="COLOR: #008000">--TGongwen是红头文件表名
[Gid][int]IDENTITY(1,1)<SPAN style="COLOR: #0000ff">NOT<SPAN style="COLOR: #0000ff">NULL,
<SPAN style="COLOR: #008000">--本表的id号,也是主键
[title]varcharCOLLATEChinese_PRC_CI_AS<SPAN style="COLOR: #0000ff">NULL,
<SPAN style="COLOR: #008000">--红头文件标题
[fariqi][datetime]<SPAN style="COLOR: #0000ff">NULL,
<SPAN style="COLOR: #008000">--发布日期
[neibuYonghu]varcharCOLLATEChinese_PRC_CI_AS<SPAN style="COLOR: #0000ff">NULL,
<SPAN style="COLOR: #008000">--发布用户
[reader]varcharCOLLATEChinese_PRC_CI_AS<SPAN style="COLOR: #0000ff">NULL,
<SPAN style="COLOR: #008000">--需要浏览的用户。每个用户中间用分隔符“,”分开
)ON[PRIMARY]TEXTIMAGE_ON[PRIMARY]
<SPAN style="COLOR: #0000ff">GO

数据库中添加1000

@iint
@i=1
@i<=250000

Tgongwen(fariqi,neibuyonghu,reader,title)(,,,)
@i=@i+1

declare @i int

set @i=1

while @i<=250000

begin

insert into Tgongwen(fariqi,title) values('2004-9-16','',',,,,,,,,,,','25')

set @i=@i+1

end

GO

@hint
@h=1
@h<=100

@iint
@i=2002
@i<=2003

@jint
@j=0
@j<50

@kint
@k=0
@k<50

Tgongwen(fariqi,title)(cast(@ivarchar(4))++cast(@jvarchar(2))++cast(@jvarchar(2)),)
@k=@k+1

@j=@j+1

@i=@i+1

@h=@h+1

@iint
@i=1
@i<=9000000

Tgongwen(fariqi,title)(,添加的900万条记录')
@i=@i+1000000

通过以上语句,我们创建了2520042525200496200220031002500502004559001000

查询优化的首要前提。

index用户定义的存储在物理介质上的数据结构。当根据索引码的值搜索数据时,索引提供了对数据的快速访问。事实上,没有索引,数据库也能根据SELECT效果就越来越明显。注意,在这句话中,我们用了“适当”这个词,这是因为,如果使用索引时不认真考虑其实现过程,索引既可以提高也会破坏数据库的工作性能

sql SERVERclustered indexnonclustered index

an文字母“azazhang内容。

内容本身就是一种按照一定规则排列的目录称为“聚集索引”。

快速地从自动中查到这个字。但您也可能会遇到您不认识的字,不知道它的发音,这时候,您就不能按照刚才的方法找到您要查的字,而需要去根据“偏旁部首”查到您要找的字,然后根据这个字后的页码直接翻到某页来找到您要找的字。但您结合“部首目录”和“检字表”而查到的字的排序并不是真正的正文的排序方法,比如您查“张”字,我们可以看到在查部首之后的检字表中“张”的页码672页码却是63页面是390页码。

方法进行排序。

修改索引列

查询2004112004101页码,然后再根据页码查到具体内容

方法。

1

错误的,是对聚集索引的一种浪费。虽然sql SERVER

IDID自动增大的,步长一般为1自动化的实例中的列Gidsql SERVER数据库中按照ID

查询要求,迅速缩小查询范围,避免全表扫描。在实际应用中,因为ID自动生成的,我们并不知道每条记录的IDID查询。这就使让IDID用户经常修改记录内容,特别是索引项的时候会负作用,但对于查询速度并没有影响。

自动化系统中,无论是系统首页显示的需要用户签收的文件、会议还是用户进行文件查询等任何情况下进行数据查询都离不开字段的是“日期”还有用户本身的“用户名”。

自动化的首页显示每个用户尚未签收的文件或会议。虽然我们的where用户尚未签收的情况,但如果您的系统已建立了很长时间,并且数据量很大,那么,每次每个用户打开首页的时候都进行一次全表扫描,这样做意义是不大的,绝大多数的用户1文件都已经浏览过了,这样做只能徒增数据库的开销而已。事实上,我们完全可以让用户打开系统首页时,数据库仅仅查询这个用户3文件,通过“日期”这个字段来限制表扫描,提高查询速度。如果您的办公自动化系统已经建立的2首页显示速度理论上将是原来速度8

ID查询速度是没有这么高的,即使您在“日期”这个字段上建立的索引(非聚合索引)。下面我们就来看一下在1000查询的速度表现(325

1

Select gid,fariqi,title from tgongwen

128470128

2fariq

gid,titleTgongwen
fariqi>dateadd(day,-90,getdate())

用时:5376354

3fariqi

gid,getdate())

用时:24232

提取出来的都是25数据库真的有1000ID12显示。这也是我摒弃ID

方法是:在各个selectdeclare @d datetime

set @d=getdate()

select

select [(datediff(ms,@d,getdate())

2查询速度

23fariqi查询速度却有着天壤之别。所以,并非是在任何字段上简单地建立索引就能提高查询速度。

1000fariqi5003文件,这几个文件的发文日期就相同,这完全符合建立聚集索引要求的:“既不能绝大多数都相同,又不能只有极少数相同”的规则。由此看来,我们建立“适当”的聚合索引对于我们提高查询速度是非常重要的。

3查询速度的字段都加进聚集索引,以提高查询速度

查询时都离不开字段的是“日期”还有用户本身的“用户名”。既然这两个字段都是如此的重要,我们可以把他们合并起来,建立一个复合索引(compound index

查询速度,也有人感到迷惑:如果把复合的聚集索引字段分开查询,那么查询速度会减慢吗?带着这个问题,我们来看一下以下的查询速度(结果集都是25fariqi用户名neibuyonghu

1select gid,title from Tgongwen where fariqi>'2004-5-5'

查询速度:2513

2select gid,title from Tgongwen where fariqi>'2004-5-5' and neibuyonghu=''

查询速度:2516

3select gid,title from Tgongwen where neibuyonghu=''

查询速度:60280

查询条件和同时用到复合聚集索引的全部列的查询速度是几乎一样的,甚至比用上全部的复合索引列还要略快(在查询结果集数目一样的情况下);而如果仅用复合聚集索引的非起始列作为查询条件的话,这个索引是不起任何作用的。当然,语句12查询速度一样是因为查询的条目数一样,如果复合索引的所有列都用上,而且查询结果少的话,这样就会形成“索引覆盖”,因而性能可以达到最优。同时,请记住:无论您是否经常使用聚合索引的其他列,但其前导列一定要是使用最频繁的列。

1

提取25

select gid,title from Tgongwen where fariqi='2004-9-16'

3326

select gid,title from Tgongwen where gid<=250000

4470

1/4

2order by

select gid,title from Tgongwen order by fariqi

12936

select gid,title from Tgongwen order by gid

18843

order by3/1010

3搜索时间会按数据占整个数据表的百分比成比例减少,而无论聚合索引使用了多少个

select gid,title from Tgongwen where fariqi>'2004-1-1'

6343提取100

select gid,title from Tgongwen where fariqi>'2004-6-6'

3170提取50

select gid,title from Tgongwen where fariqi='2004-9-16'

3326数量一样,那么用大于号和等于号是一样的)

select gid,title from Tgongwen where fariqi>'2004-1-1' and fariqi<'2004-6-6'

3280

4 查询速度

10020041150505000

select gid,title from Tgongwen where fariqi>'2004-1-1' order by fariqi

6390

select gid,title from Tgongwen where fariqi<'2004-1-1' order by fariqi

6453

性能,但过多或不当的索引也会导致系统低效。因为用户在表中每加进一个索引,数据库就要做更多的工作。过多的索引甚至会导致索引碎片。

数据库能得到高性能的发挥。

数据库管理员,您还要多测试一些方案,找出哪种方案效率最高、最为有效。

sql

sqlsql SERVERsqlsql SERVER

select * from table1 where name='zhangsan' and tID > 10000

:

select * from table1 where tID > 10000 and name='zhangsan'

tID10000name='zhangsan'tID>10000查询结果。

sql SERVER查询分析优化器”,它可以计算出where搜索条件并确定哪个索引能缩小表扫描的搜索空间,也就是说,它能实现自动优化。

查询优化器可以根据where自动的进行查询优化,但大家仍然有必要了解一下“查询优化器”的工作原理,如非这样,有时查询优化器就会不按照您的本意进行快速查询

查询分析阶段,查询优化器查看查询的每个阶段并决定限制需要扫描的数据量是否有用。如果一个阶段可以被用作一个扫描参数(SARG快速获得所需数据。

SARG搜索的一个操作,因为它通常是指一个特定的匹配,一个值得范围内的匹配或者两个以上条件的AND

< >

< >

Name=

>5000

5000<

Name= and >5000

SARG搜索的范围了,也就是sql SERVERWHERESARG

SARGSARG

1LikeSARG通配符的类型

name like % SARG

name like %,SARG

通配符%

2or

Name= and >5000 SARGName= or >5000 SARGor

3函数引起的不满足SARG

SARG包括非操作符的语句,如:NOT!=<>!<!>NOT EXISTSNOT INNOT LIKE函数。下面就是几个不满足SARG

ABS()<5000

Name like %

WHERE *2>5000

sql SERVERSARGsql SERVER

WHERE >2500/2

sql SERVER

4IN OR

Select * from table1 where tid in (2,3)

Select * from table1 where tid=2 or tid=3

tid

5NOT

6exists in

显示说,existsinnot existsnot innot查询,我们试验这次用sql SERVER自带的pubs数据库。运行前我们可以把sql SERVERstatistics I/O

1select title,price from titles where title_id in (select title_id from sales where qty>30)

'sales' 18 56 0 0

'titles' 1 2 0 0

2select title,price from titles where exists (select * from sales where sales.title_id=titles.title_id and qty>30)

'sales' 18 56 0 0

'titles' 1 2 0 0

existsin

7函数charindex()通配符%LIKE

LIKE加上通配%函数charindex()LIKE错误的:

select gid,title,reader from tgongwen where charindex('',reader)>0 and fariqi>'2004-5-5'

7 4 7155 0 0

select gid,reader from tgongwen where reader like '%' + '' + '%' and fariqi>'2004-5-5'

7 4 7155 0 0

8unionor

whereorunionor

select gid,title from Tgongwen where fariqi='2004-9-16' or gid>9990000

68 1 404008 283 392163

select gid,title from Tgongwen where fariqi='2004-9-16'

union

select gid,title from Tgongwen where gid>9990000

9 8 67489 216 7499

unionor

or查询列是一样的话,那么用unionorunionor

select gid,title from Tgongwen where fariqi='2004-9-16' or fariqi='2004-2-5'

6423 2 14726 1 7176

select gid,title from Tgongwen wherefariqi='2004-2-5'

11640 8 14806 108 1144

9提取要按照“需多少、提多少”的原则,避免“select *

select top 10000 gid,title from tgongwen order by gid desc

4673

select top 10000 gid,title from tgongwen order by gid desc

1376

select top 10000 gid,fariqi from tgongwen order by gid desc

80

提取一个字段,数据的提取速度就会有相应的提升。提升的速度还要看您舍弃的字段的大小来判断。

10count(*)count()

*统计所有列,显然要比一个世界的列名效率低。这种说法其实是没有根据的。我们来看:

select count(*) from Tgongwen

1500

select count(gid) from Tgongwen

1483

select count(fariqi) from Tgongwen

3140

select count(title) from Tgongwen

52050

count(*)count()count(*)count(*) sql SERVER自动查找最小字段来汇总的。当然,如果您直接写count()

11order by

gidfariqi

select top 10000 gid,title from tgongwen

196 1 289 1 1527

select top 10000 gid,title from tgongwen order by gid asc

4720 1 41956 0 1287

select top 10000 gid,title from tgongwen order by gid desc

4736 1 55350 10 775

select top 10000 gid,title from tgongwen order by fariqi asc

173 1 290 0 0

select top 10000 gid,title from tgongwen order by fariqi desc

156 1 289 0 0

次数都是和“order by order by 查询速度是快得多的。

12TOP

查询和提取超大容量的数据集时,影响数据库响应时间的最大因素不是数据查找,而是物理的I/0

select top 10 * from (

select top 10000 gid,title from tgongwen

where neibuyonghu=''

order by gid desc) as a

order by gid asc

1000010数据库响应时间最大的因素是物理I/OI/O方法之一就是使用TOPTOPsql SERVER提取前几条或前几个百分比数据的词。经笔者在实践中的应用,发现TOP数据库ORACLEORACLE方法(如:rownumber解决。在以后的关于“实现千万级数据的分页显示存储过程”的讨论中,我们就将用到TOP

数据库中快速查询出您所需要的数据方法。当然,我们介绍的这些方法都是“软”方法,在实践中,我们还要考虑各种“硬”因素,如:网络性能、服务器的性能、操作系统的性能,甚至网卡、交换机等。

分页显示存储过程

web 分页浏览功能必不可少。这个问题是数据库处理中十分常见的问题。经典的数据分页方法:ADO 分页法,也就是利用ADO自带的分页功能(利用游标)来实现分页。但这种分页方法仅适用于较小数据量的情形,因为游标本身有缺点:游标是存放在内存中,很费内存。游标一建立,就将相关的记录锁住,直到取消游标。游标提供了对特定集合中逐行扫描的手段,一般使用游标来逐行遍历数据,根据取出数据条件的不同进行不同的操作。而对于多表和大表中定义的游标(大的数据集合)循环很容易使程序进入一个漫长的等待甚至死机。

分页检索时,如果按照传统的每次都加载整个数据源的方法是非常浪费资源的。现在流行的分页方法一般是检索页面大小的块区的数据,而非检索所有的数据,然后单步执行当前行。

页面大小和页码提取数据的方法大概就是“俄罗斯存储过程”。这个存储过程用了游标,由于游标的局限性,所以这个方法并没有得到大家的普遍认可。

自动化实例写的分页存储过程:

pagination1
(@pagesizeint,页面大小,如每页存储20条记录
@pageindexint页码
)

nocounton

@indextable(idintidentity(1,1),nidint)
@PageLowerBoundint
@PageUpperBoundint
@PageLowerBound=(@pageindex-1)*@pagesize
@PageUpperBound=@PageLowerBound+@pagesize
rowcount@PageUpperBound
@indextable(nid)gidTGongwenfariqi>dateadd(day,-365,getdate())fariqi
O.gid,O.mid,O.title,O.fadanwei,O.fariqiTGongwenO,@indextabletO.gid=t.nid
t.id>@PageLowerBoundt.id<=@PageUpperBoundt.id

nocountoff

以上存储过程运用了sql SERVER分页存储过程。当然,在这个过程中,您也可以把其中的表变量写成临时表:CREATE TABLE #Tempsql SERVERADO方法更好的方法

nm方法》,全文如下:

publish n m

TOPm-n+1*
publish
(id
    (TOPn-1id
    publish))

id publish

文章的时候,真的是精神为之一振,觉得思路非常得好。等到后来,我在作办公自动化系统(ASP.NET+ C#sql SERVER文章,我想如果把这个语句改造一下,这就可能是一个非常好的分页存储过程。于是我就满网上找这篇文章,没想到,文章还没找到,却找到了一篇根据此语句写的一个分页存储过程,这个存储过程也是目前较为流行的一种分页存储过程,我很后悔没有争先把这段文字改造成存储过程:

pagination2
(
@sqlnVARCHAR(4000),sql语句
@Pageint,页码
@RecsPerPageint,
@IDVARCHAR(255),
@SortVARCHAR(255)
)

@StrnVARCHAR(4000)
@Str=+CAST(@RecsPerPageVARCHAR(20))++@sql++@ID+
(TOP(sql+')T9)
PRINT@Str
sp_Executesql@Str

其实,以上语句可以简化为:

TOP页大小*
Table1
(ID
(TOP页大小*页数id

id))
ID

但这个存储过程有一个致命的缺点,就是它含有NOT IN

TOP页大小*
Table1

(*(top(页大小*页数)*table1id)bb.id=a.id)
id

即,用not existsnot in

TOP NOT IN方法还是比用游标要来得快一些。

not existssql SERVERTOP分页优化的最终目的就是避免产生过大的记录集,而我们在前面也已经提到了TOPTOP

分页算法中,影响我们查询速度的关键因素有两点:TOPNOT INTOP查询速度,而NOT IN查询速度,所以要提高我们整个分页算法的速度,就要彻底改造NOT IN方法来替代它。

max()min()提取某个字段中的最大或最小值,所以如果这个字段不重复,那么就可以利用这些不重复的字段的maxmin分页算法中分开每页的参照物。在这里,我们可以用操作符“><查询语句符合SARG

Select top 10 * from table1 where id>200

分页方案:

top页大小*
table1
id>
((id)
(top((页码-1)*页大小)idtable1id)T
)
id

在选择即不重复值,又容易分辨大小的列时,我们通常会选择主键。下表列出了笔者用有着1000自动化系统中的表,在以GIDGID提取gid,title11010050010001102550分页方案的执行速度:(单位:毫秒)

1 2 3

1 60 30 76

10 46 16 63

1001076 720130

50054012943 83

1000 17110 470250

1 24796 4500 140

10 38326 42283 1553

25 28140 128720 2330

50 121686 127846 7168

100分页命令时,都是可以信任的,速度都很好。但第一种方案在执行分页1000分页1

分页方案后,我们可以据此写一个存储过程。大家知道sql SERVERsqlWEB页面传来的sql分页方案,还会根据页面传来的参数来确定是否进行数据总数统计

-- 获取指定页的数据

pagination3
@tblNamevarchar(255),
@strGetFieldsvarchar(1000)=,
@fldNamevarchar(255)=,
@PageSizeint=10,
@PageIndexint=1,页码
@doCountbit=0,
@OrderTypebit=0,
@strWherevarchar(1500)=查询条件(注意:不要加where)

@strsqlvarchar(5000)
@strTmpvarchar(110)
@strOrdervarchar(400)@doCount!=0

@strWhere!=
@strsql=+@tblName++@strWhere

@strsql=+@tblName+

代码的意思是如果@doCount传递过来的不是0,就执行总数统计。以下的所有代码都是@doCount为0的情况

@OrderType!=0

@strTmp=
@strOrder=+@fldName+




@strTmp=
@strOrder=+@fldName+
@PageIndex=1

@strWhere!=
@strsql=+str(@PageSize)++@strGetFields++@tblName++@strWhere++@strOrder

@strsql=+str(@PageSize)++@strGetFields++@tblName++@strOrder
代码,这样会加快执行速度



代码赋予了@strsql以真正执行的sql代码
@strsql=+str(@PageSize)++@strGetFields+
+@tblName++@fldName++@strTmp++@fldName++str((@PageIndex-1)*@PageSize)++@fldName++@tblName++@strOrder++@strOrder@strWhere!=
@strsql=+str(@PageSize)++@strGetFields+
+@tblName++@fldName++@strTmp+
+@fldName++str((@PageIndex-1)*@PageSize)+
+@fldName++@tblName++@strWhere+
+@strOrder++@strWhere++@strOrder


(@strsql)

上面的这个存储过程是一个通用的存储过程,其注释已写在其中了。

查询最后几页的时候,查询时间一般不会超过9数据库的查询

分页算法。

标题中,笔者写的是:实现小数据量和海量数据的通用分页显示存储过程。这是因为在将本存储过程应用于“办公自动化”系统的实践中时,笔者发现这第三种存储过程在小数据量的情况下,有如下现象:

1分页速度一般维持在13

2查询最后一页时,速度一般为58分页总数只有330

分页的实现过程是很快的,但在分前几页时,这个13分页方法速度还要慢,借用户的话说就是“还没有ACCESS数据库速度快”,这个认识足以导致用户放弃使用您开发的系统。

文章的题目是:“查询优化及分页算法方案”。笔者只所以把“查询优化”和“分页算法”这两个联系不是很大的论题放在一起,就是因为二者都需要一个非常重要的东西――聚集索引。

1查询范围。

2

1查询优化时,而第2分页时的数据排序。

查询优化”和“高效分页”的最关键因素。

查询列的需要,又符合排序列的需要,这通常是一个矛盾。

fariqi用户发文日期作为了聚集索引的起始列,日期的精确度为“日”。这种作法的优点,前面已经提到了,在进行划时间段的快速查询中,比用ID

分页时,由于这个聚集索引列存在着重复记录,所以无法使用maxmin分页的参照物,进而无法实现更为高效的排序。而如果将ID

解决这个矛盾,笔者后来又添加了一个日期列,其默认值为getdate()用户在写入记录时,这个列自动写入当时的时间,时间精确到毫秒。即使这样,为了避免可能性很小的重合,还要在此列上创建UNIQUE

用户就既可以用这个列查找用户在插入数据时的某个时间段的查询,又可以作为唯一列来实现maxmin分页算法的参照物。

分页速度一般都是几十毫秒,甚至0查询速度比原来也没有任何迟钝。

1查询范围的字段上;

2比如
“主键就是聚集索引
这种想法笔者认为是极端错误的,是对聚集索引的一种浪费。虽然sql SERVER默认是在主键上建立聚集索引的。”
我觉得应该给主键加上聚集索引。 他的测试数据也有问题,同一天内的记录居然有25万条,2004年5月5日的竟然达到了900万条记录。
这样的测试数据就导致了测试结果的普遍性。
也就是说他的测试产生的结论可能只适合1000万条记录、不平均分布的情况,却不适合几十万条记录、平均分布的情况。

猜你在找的MsSQL相关文章