標簽歸檔:adodb

PHP連接Access的方法

最近準備放棄使用許久的vbscript作為處理工作方面問題,而轉向PHP。
應該是ASP轉向PHP把,怎么是vbscript轉向php?這個我要說一下,處理工作方面問題,比如通過API導個數據…用ASP,PHP在IIS中執行肯定不行,寫個VBScript腳本,cscript 腳本名 讓他執行吧,別的不用關了。所以用腳本處理些數據轉換、導入導出還是不錯的選擇。
VBScript的致命的缺點是不支持引用文件,對HTTP請求方便不是很強,正則、XML處理起來不方面,JSON作為數據載體時就等著傻眼把。這是后用php作為腳本也是一個不錯的選擇。扯得有點遠了,換成了php,數據庫還是Access怎么辦?這個簡單,直接用com創建adodb實例即可。
現在已經創建好了數據庫,只填寫了部分域名,要通過php到域名查詢接口返回whois信息,并存到Access數據庫中,Access字段名已對應返回數組中的索引相同。

<?php
	set_time_limit(0);

	#因為要鏈接web,使用我前幾天寫的myhttp類。
	include('myhttp.clsss.php');
	#API操作,這里直接忽略,里邊有個get_domain_info來獲取API返回的數據,并處理成數組。
	include('api.function.php');
	
	$conn = new COM("Adodb.Connection");
	$conn -> open("provider=microsoft.jet.oledb.4.0;data source=D:\myweb\miaoqiyuan.cn\test\php-linkdb\domain.mdb");
	
	$dlist = new COM("ADODB.Recordset");
	$rs = new COM("ADODB.Recordset");
	
	$dlist -> open("select [domain],[did] from [domain] where isupdate=0",$conn,1,1);
	while(!$dlist -> eof()){
		echo "下載域名數據[".$dlist['domain']."].\n";
		$d=get_domain_info($dlist['domain']);
		$rs -> open("select * from [domain] where  did=".$dlist['did'],$conn,3,2);
		foreach($rs -> fields as $k => $v){
			if($k >= 6){
				$myvalue = $d[$rs[$k] -> name];
				if(isset($myvalue) && !is_array($myvalue)){
					$rs[$k] -> value = mb_convert_encoding($myvalue,"GB2312","UTF-8");
				}
			}
		}
		$rs['isupdate'] -> value = 2;
		$rs -> update();
		$rs -> close();
		$dlist -> movenext();
	}
?>

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倍。這個結果您信嗎?不信,更我來一起做這個測試。貓七(苗啟源)博客首發,轉載請注明出處,原文地址: (http://www.shiekolong331.icu/p/conn-execute_rs-getrows)。

數據說明真相。首先創建一個多記錄的數據庫。

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.shiekolong331.icu','e10adc3949ba59abbe56e057f20f883e')")
loop

經過幾個小時的運行,我得到了一個有63萬多條記錄的數據庫。數據庫大小為99.7MB(測試數據庫下載地址http://www.shiekolong331.icu/products/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,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",conn,1,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)&":"&res(1,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",conn,1,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)&":"&res(1,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倍。囧。。。。貓七(苗啟源)博客首發,轉載請注明出處,原文地址: (http://www.shiekolong331.icu/p/conn-execute_rs-getrows)。

難道set rs=conn.execute就一無是處了嗎?在數據插入方面,兩者的差別有多大呢?詳情請關注我的博客(http://www.shiekolong331.icu)今天太累了,就寫這些吧~

ASP使用BinaryWrite與Adodb.Stream實現下載

因為某種原因要實現一個RAR的文件的下載,而且為了節省服務器資源,需要做一個判斷,下載引用方法如下:

   	<input type="button" value="下載工具包" onclick="location.href='http-localhost-api?/easywork-imageupload-client-full/download/port-80/ver=<%=date%/>.gzip.rar';">
   	<input type="button" value="下載升級包" onclick="location.href='http-localhost-api?/easywork-imageupload-client-fast/download/port-80/ver=<%=date%/>.gzip.rar';">

初步打算用FSO讀取為TextStream,然后用BinaryWrite輸出,代碼如下:

< %@codepage=65001%>
< %
response.buffer=false
if session("safe_mode")<>"ok" then response.write "<form action=""../../../admin.asp"" method=""post"" id=""a""><script type=""text/javascript"">document.getElementById(""a"").submit();</script>":response.end
if instr(request.Querystring,"/")< =0 then response.redirect "/":response.end
set fso=server.createobject("Scripting.FileSystemObject")
file=server.mappath(split(request.QueryString,"/")(1)&".rar")
if not fso.fileexists(file) then response.redirect "/":response.end
set fto=fso.getfile(file)
set fts=fto.OpenAsTextStream(1,-1)
 
Response.ContentType = "application/octet-stream"
Response.AddHeader "Content-Disposition","attachment;filename="&split(request.QueryString,"/")(1)&".rar"
 
response.binarywrite fts.readall
%>
</form>

實際運行時速度不是很快,可能是fts.readall的原因吧,于是修改一下代碼,一行一行的輸出:

< %@codepage=936%>
< %
response.buffer=false
if session("safe_mode")<>"ok" then response.write "<form action=""../../../admin.asp"" method=""post"" id=""a""><script type=""text/javascript"">document.getElementById(""a"").submit();</script>":response.end
if instr(request.Querystring,"/")< =0 then response.redirect "/":response.end
set fso=server.createobject("Scripting.FileSystemObject")
file=server.mappath(split(request.QueryString,"/")(1)&".rar")
if not fso.fileexists(file) then response.redirect "/":response.end
set fto=fso.getfile(file)
set fts=fto.OpenAsTextStream(1,-1)
 
 
Response.ContentType = "application/octet-stream"
Response.AddHeader "Content-Disposition","attachment;filename="&split(request.QueryString,"/")(1)&".rar"
do while not fts.atendofstream
	response.binarywrite fts.readall
loop
%>
</form>

效率有所提高,因為FSO每次讀取硬盤,速度很慢~到網上搜索了一下,發現Adodb中除了Connection和Recordset,還有一個Stream,于是有了第三種方法:

< %@codepage=65001%>
< %
response.buffer=false
if session("safe_mode")<>"ok" then response.write "<form action=""../../../admin.asp"" method=""post"" id=""a""><script type=""text/javascript"">document.getElementById(""a"").submit();</script>":response.end
if instr(request.Querystring,"/")< =0 then response.redirect "/":response.end
set fso=server.createobject("Scripting.FileSystemObject")
file=server.mappath(split(request.QueryString,"/")(1)&".rar")
if not fso.fileexists(file) then response.redirect "/":response.end
 
Response.ContentType = "application/octet-stream"
Response.AddHeader "Content-Disposition","attachment;filename="&now&".rar"
 
Set Ados=Server.CreateObject("Adodb.Stream")
Ados.Mode=3
Ados.Type=1
Ados.Open
Ados.LoadFromFile(Server.mappath(split(request.QueryString,"/")(1)&".rar"))
 
response.binarywrite Ados.read()
%>
</form>

速度已經不錯了,同時很多人訪問CPU占用也不是很高。