1. 程式人生 > 程式設計 >set rs=conn.execute,set rs=server.createobject(“ADODB.recordset”)的效能對比

set rs=conn.execute,set rs=server.createobject(“ADODB.recordset”)的效能對比

經常用asp的同行,可能會建議用set rs=conn.execute(sql)來代替set rs=server.createobject(“ADODB.recordset”):rs.open conn,sql,1,1。還有一些同行更提出了用set rs=conn.execute(sql):res=rs.getRows(100)來優化ASP程式。其實在沒有做此實驗前,我也是很相信這種方法的。實際效果果真如此嗎?經過一番測試,我發現結果遠非如此,set rs=server.createobject(“ADODB.recordset”)的方法比set rs=conn.execute的方法快4~5倍。這個結果您信嗎?不信,更我來一起做這個測試。

資料說明真相。首先建立一個多記錄的資料庫。

set conn=createobject("adodb.connection")
conn.open "provider=microsoft.jet.oledb.4.0;data source=E:\labs\miaoqiyuan.cn\g.mdb"
do while conn.execute("select count(id) from site")(0)<1000000
	conn.execute("insert into site(sitename,siteadmin,siteurl,sitekey) values('苗啟源','http://localhost/app_login/','http://www.miaoqiyuan.cn','e10adc3949ba59abbe56e057f20f883e')")
loop

經過幾個小時的執行,我得到了一個有63萬多條記錄的資料庫。資料庫大小為99.7MB(測試資料庫下載地址rs-execute-test.rar)。

為了保證資料的真實性,我們用公共的頭部header.asp來儲存資料庫連線字串。footer.asp來儲存執行時間。

執行環境,Windows 2003 Server SP2。IIS6.0,CPU E2200 2.2GHz,記憶體2Gx2。硬碟300G SATA+80G ATA。

公共頭部:header.asp

<%
startTme=timer()
set conn=server.createobject("ADODB.connection")
conn.open "provider=microsoft.jet.oledb.4.0;data source="&server.mappath("g.mdb")
%>

公共底部:footer.asp

<hr />總共用時:< %=(timer()-startTme)*1000%>毫秒

測試方法:以三種方式,每頁100條記錄。同時讀取第6000頁到6099頁的記錄共一萬條,並測出執行時間。

test1.asp,採用set rs=server.createobject(“ADODB.recordset”)的方法。

< %
for k=0 to 100
	response.write "<br /><br />第"&(6000+k)&"頁<hr />"

	set rs=server.createobject("adodb.recordset")
	rs.open "select * from site",conn,1
	rs.pagesize=100
	rs.absolutepage=6000+k
	i=0
	do while not rs.eof and i<100
		i=i+1
		response.write rs("id")&":"&rs("sitename")&"<br />"&vbCrlf
		rs.movenext
	loop
	rs.close
	set rs=nothing

next
%>

test2.asp 採用set rs=conn.execute()的方法

< %
for k=0 to 100
	response.write "<br /><br />第"&(6000+k)&"頁<hr />"

	set rs=conn.execute("select * from site")
	rs.movefirst
	rs.move (6000+k)*100
	i=0
	do while not rs.eof and i<100
		i=i+1
		response.write rs("id")&":"&rs("sitename")&"<br />"&vbCrlf
		rs.movenext
	loop
	rs.close
	set rs=nothing

next
%>

至於getRows,這種方法只能算是返回結果的優化,並不能算是一種方法。我們採用兩種返回結果的方式測試。test3.asp採用set rs=server.createobject(“ADODB.recordset”)的方法,test4.asp採用set rs=conn.execute(sql)的方法

< %
for k=0 to 100
	response.write "<br /><br />第"&(6000+k)&"頁<hr />"

	set rs=server.createobject("adodb.recordset")
	rs.open "select * from site",1
	rs.pagesize=100
	rs.absolutepage=6000+k
	res=rs.getRows(100)
	rs.close
	set rs=nothing
	for i=0 to 99
		response.write res(0,i)&":"&res(1,i)&"<br />"&vbCrlf
	next

next
%>
< %
for k=0 to 100
	response.write "<br /><br />第"&(6000+k)&"頁<hr />"

	set rs=conn.execute("select * from site")
	rs.movefirst
	rs.move (6000+k)*100
	res=rs.getRows(100)
	rs.close
	set rs=nothing
	for i=0 to 99
		response.write res(0,i)&"<br />"&vbCrlf
	next

next
%>

下面是我的測試結果:

檔名 test1.asp test2.asp test3.asp test4.asp
第一次測試 4281.25毫秒 20656.25毫秒 4281.25毫秒 18671.88毫秒
第二次測試 4234.375毫秒 25171.88毫秒 4312.5毫秒 13781.25毫秒
第三次測試 4328.125毫秒 20031.25毫秒 4234.375毫秒 19093.75毫秒

為什麼會出現這種結果呢?set rs=conn.execute(sql),set rs=server.createobject(“ADODB.recordset”)為什麼為相差這麼多?對比一下test1.asp、test3.asp與test2.asp、test4.asp,除了返回結果的方式不同,還有一處就是rs.move。難道是這個原因?把test3.asp的程式碼稍微修改一下。存為test5.asp。

< %
for k=0 to 100
	response.write "<br /><br />第"&(6000+k)&"頁<hr />"

	set rs=server.createobject("adodb.recordset")
	rs.open "select * from site",1
	rs.movefirst
	rs.move (6000+k)*100
	res=rs.getRows(100)
	rs.close
	set rs=nothing
	for i=0 to 99
		response.write res(0,i)&"<br />"&vbCrlf
	next

next
%>

經過測試,test5.asp能比test3.asp快0.1~0.2秒,如果讀取100條資料,這點差距可以忽略不計。

由此可見:set rs=conn.execute的方式確實比set rs=server.createobject(“ADODB.recordset”)方式慢,在學校的時候,老師教的一般都是set rs=server.createobject(“ADODB.recordset”)的方法,真正工作室,學習所謂的高手set rs=conn.execute優化的方法,結果最終發現,而鄙視用老師教的方法寫程式的同行,最終發現還是老師教的速度快,而且set rs=server.createobject(“ADODB.recordset”)的方法比set rs=conn.execute的方法快4~5倍。囧。。。。

難道set rs=conn.execute就一無是處了嗎?在資料插入方面,兩者的差別有多大呢?

下面是其他網友的補充

沒有可比性,為什麼非要比呢?
set rs=conn.execute()
rs.getrows()
這種方法一般用在資料量少的情況下,比如說只有幾十幾百條資料的情況下,它只讀一次資料庫,然後把結果存入一個二維陣列中,在這之後的操作就不需要資料庫,而是直接對記憶體中的資料進行操作了,速度絕對比用常規方法快,而且也節省資源。而用常規方法的話,資料庫操作得多少次?而在日常的情況下,一次讀取大量資料的情況是很少的,所以在很多地方都提到使用上面這種方法,就是緣於此。
還有上面比的分頁,常規方法由於它自身的侷限,對資料庫的操作很費資源的,別說只是快那零點幾秒,好的程式到最後拼的就是那零點幾秒。

rs.open sql,conn 與conn.execute(sql)的區別

什麼時候用什麼?
那就憑個人經驗積累的感覺了:
如果只需要一筆帶過的碰碰資料庫,用execute
如果要對資料庫作比較龐雜的操作!則最好用 rs.open

rs.open sql,conn:如果sql是delete,update,insert則會返回一個關閉的記錄集,在使用過程中不要來個rs.close在檔案最後再寫rs.close中間可以來多個記錄集rs1.open sql1,conn,最後一塊關閉記錄集:rs.close rs1.close

conn.execute(sql):如果sql是update,insert,delete則應該使用conn.execute(sql)也可以不要括號conn.execute sql

如果sql是select語句則應該使用set rs=conn.execute(sql)括號一定要,不能省略:這是因為vb的特性,帶返回值的呼叫必須加括號,不帶返回值的呼叫可以不要括號。

1.conn.execute

sql="select * from admin where username='xiaozhu'"
set rs=conn.execute(sql)
'執行完以後自動關閉記錄集
'最後只需要關閉連線就可以了
conn.close
set conn=nothing

2.rs.open

set rs=server.createobject("adodb.recordset")
sql="select * from admin where username='xiaozhu'"
rs.open sql,1
'可以自己設定一些引數,即鎖定和遊標的移動方式
'最後要關閉記錄集和連線
rs.close
set rs=nothing
conn.close
set conn=nothing

3.command.execute

sql="select * from admin where username='xiaozhu'"
set rs=command.execute(sql)

1.
set rs=conn.execute("如果是select語句") 得到的rs.recordcount=-1
rs.open sql,conn("sql為select語句") 得到的rs.recordcount為正常的記錄數


2.
rs.open是開啟資料庫 conn.execute 是執行SQL指令
set rs=conn.execute(insert,delete)返回一個關閉了的記錄集
set rs=conn.execute(select)返回一個沒有關閉的記錄集

3.
CONN.EXECUTE(SQL,RowsAffected,C)

引數含義:

SQL的值可以是SQL語句、表名、儲存過程名,也可以是資料提供者所能接受的任意字串。為了提高效能,最好為C引數指定合適的值

可選引數RowsAffected將返回INSERT、UPDATE或DELETE查詢執行以後所影響的數目。這些查詢會返回一個關閉的Recordset物件。

一個SELECT查詢將返回RowsAffected值為-1並且返回帶有一行或多行內容的開啟的Recordset。

4.
conn.execute sql適合於不需返回recordset物件時使用,比如下面的程式碼:
sql="delete from enews where id="&cstr(id)
conn.execute sql

如果需要返回recordset物件,則使用如下程式碼:
sql="select from enews where id="&cstr(id)
set rs = conn.execute(sql)

如果去掉execute(sql)這兒的括號(即為set rs = conn.execute sql),就會提示“語句未結束”這樣的錯誤提示,我翻看了一下語法格式,發現有二種格式,詳解如下:

格式一:Connection物件名.Execute(SQL指令).
格式二:Connection物件名.Execute(資料表名)。
附:

set rs = conn.execute(sql)

是帶有返回值的,一般sql為查詢的時候使用。如
set rs = conn.execute("select * from ...")
當然執行insert into 和delete也是可以的
set rs = conn.execute("insert into table (f1,f2..")
但是要建立Recordset物件,佔用伺服器資源。在insert into,delete的時候我們一般不需要返回記錄集。所以我是這樣認為的:

在使用查詢的時候,用 set rs = conn.execute("select * from table")
在插入和刪除時候,用 conn.execute("delete from table where ...")

第二種方式程式碼簡潔,不需要顯式地建立Recordset物件(但實際上好象是隱式建立的)

第二種方法還有一些簡潔的寫法:如,最某表的記錄數

dim count
count = conn.execute(select count(*) from table)(0)
上面的語句等於
count = conn.execute(select count(*) from table).fields(0).value

綜上:區別在於set rs = conn.execute是顯示建立recordset物件,而conn.execute是隱式的。
能用conn.execute的時候就用conn.execute,好處有
一、程式碼簡潔
二、效率應該有所提高

再摘引一下:(srnld(天涯))

形成記錄集的方法有三種 CONN.execute rs.open Command.execute
方法用法大大不通

通常 Set rs=CONN.execute(SQL)
或直接 rs=CONN.execute(SQL)

和 Set rs=Server.CreateObject("ADODB.Recordset")
rs.open SQL,CONN,1 或 rs.open SQL,CONN
這種情況 通常open比上一個效能要好那麼一丁點
( command物件更靈活,執行範圍更廣)

使用 CONN.execute 可以不用關閉直接執行下一個 set rs=conn.execute(SQL)
但效能速度會大打折扣!!
大約要慢 2~5倍!!(這是我在msSQL迴圈1000次親自測試過的,不信你馬上自己測試),所以執行下一個 rs=conn.execute之前!!一定要關閉掉!是個好習慣!
使用單一物件的rs rs.open在open下一個記錄集之前,必需要求顯示關閉,否則出錯,速度在SQL,1的情況下可前者基本一樣

所以我喜歡使用直設定一個 CreateObject("adodb.recordser")(在不需要多個記錄集交錯操作的情況下,多個也不礙是!)
然後從頭用到尾!!!
開門關門開門關門~~~~~咵踏咵踏~~~~
最後一個 set rs=nothing 化上句號,爽!

更主要是 open提供非常靈活的操作資料庫元資料的非常多的屬性!!
開啟百寶箱,金光燦燦什麼都看見!
有很多情況下是非得用open來做的!
而conn.execute 想黑布下換膠捲~~~偷偷摸摸~~非常單一!!!

比如:

rs1.open SQL1,1
rs.open SQL,3
if rs(0)<0 then rs(0)=0
rs(1)=aaa
rs(2)=bbb
rs.update ' 更新記錄集寫到資料庫

rs.addnew '加一條新記錄
rs(0)=1
rs(1)=ddd
rs(2)=kkk
rs.update
id=rs(3) rs(s) '取的欄位是自動編號 立即獲得新記錄的自動編號id //這是非常常用的

rs1.addnew 對rs1新增關連使用id rs的新記錄
rs1("id")=id
rs1(1)=...
..
rs1.update

rs1.close:set rs1=nothing
rs.close:set rs=nothing


上面的操作如果採用CONN.execute 則要用到四個 CONN.execute

CONN.execute("update ..")
CONN.execute("insert into 表1:")
rs=CONN.execute("select 新的自動 id")
CONN.execute("insert into 表二")
那一種方法邏輯條理更好~~一目瞭然

======================

還有一個有趣的使用Recordset open記錄的方法!!
我想起來是有點費解

Set rs=server.CreateObject("Adodb.recordset")
Set rs=server.CreateObject("Adodb.recordset")

rs.open SQL1,CONN
rs.open SQL2,CONN

'嘿嘿~~~這是同時設定同名的兩個物件來開啟兩個記錄集,而且是可用的!
'只要取的列名合乎這兩個記錄集中元資料
'則正常操作!!
擴充套件開來

Set rs=server.CreateObject("Adodb.recordset")
Set rs=server.CreateObject("Adodb.recordset")
Set rs=server.CreateObject("Adodb.recordset")
Set rs=server.CreateObject("Adodb.recordset")

rs.open SQL1,CONN
rs.open SQL3,CONN
rs.open SQL4,CONN

這樣大於二個同名的 rs我還沒試過!!

感覺有點相當與 SQL聯合查詢再開啟記錄集~~~
以前我這樣用過!!應該不是眼花!!

到此這篇關於set rs=conn.execute,set rs=server.createobject(“ADODB.recordset”)的效能對比的文章就介紹到這了,更多相關conn.execute與ADODB.recordset的對比內容請搜尋我們以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援我們!