我想知道,以下哪个示例最适合在我的情况下关闭记录集对象?
1)
这个关闭循环内的对象,但在下一个移动时打开一个新对象。如果有1000条记录,则会打开一个对象1000次并关闭1000次。这就是我通常会做的事情:
SQL = " ... "
Set rs1 = conn.Execute(SQL)
While NOT rs1.EOF
SQL = " ... "
Set rs2 = conn.Execute(SQL)
If NOT rs2.EOF Then
Response.Write ( ... )
End If
rs2.Close : set rs2 = Nothing
rs1.MoveNext
Wend
rs1.Close : Set rs1 = Nothing
2)
这个例子是我想知道的。在循环结束之后保存对象闭包(rs2.close),是获得还是降低性能?如果有1000条记录,这将打开1000个对象,但只关闭一次:
SQL = " ... "
Set rs1 = conn.Execute(SQL)
While NOT rs1.EOF
SQL = " ... "
Set rs2 = conn.Execute(SQL)
If NOT rs2.EOF Then
Response.Write ( ... )
End If
rs1.MoveNext
Wend
rs1.Close : Set rs1 = Nothing
rs2.Close : set rs2 = Nothing
我希望自己能够很好地解释自己,这并不是太愚蠢。
更新
对于那些认为我的查询可以修改以避免N + 1问题(第二次查询)的人,这里是:
这是一个在线图片库。我有两张桌子; “photoSearch”和“照片”。第一个“photoSearch”只有几列,包含照片的所有可搜索数据,例如“photoID”,“标题”,“标题”,“人物”,“dateCaptured”和“关键字”。它有一个多列全文索引(标题,标题,人物,关键字)。第二张表“照片”包含所有照片数据;高度,宽度,版权,标题,ID,日期等等。两者都有500K +行,标题和标题字段有时会返回2000多个字符。
这大约是查询现在的样子: (注意事项:我不能使用全文搜索的连接,因此关键字存储在一个列中 - 在'去规范化'表中。此外,这种伪代码作为我的应用程序代码在其他地方 - 但它很接近)
SQL = "SELECT photoID FROM photoSearch
WHERE MATCH (headline, caption, people, keywords)
AGAINST ('"&booleanSearchStr&"' IN BOOLEAN MODE)
AND dateCaptured BETWEEN '"&fromDate&"' AND '"&toDate&"' LIMIT 0,50;"
Set rs1 = conn.Execute(SQL)
While NOT rs1.EOF
SQL = "SELECT photoID, setID, eventID, locationID, headline, caption, instructions, dateCaptured, dateUploaded, status, uploaderID, thumbH, thumbW, previewH, previewW, + more FROM photos LEFT JOIN events AS e USING (eventID) LEFT JOIN location AS l USING (locationID) WHERE photoID = "&rs1.Fields("photoID")&";"
Set rs2 = conn.Execute(SQL)
If NOT rs2.EOF Then
Response.Write ( .. photo data .. )
End If
rs2.Close
rs1.MoveNext
Wend
rs1.Close
经过测试,在自己的桌子上有全文索引,“photoSearch”,而不是大桌子,“照片”,似乎有点提高了速度。我没有添加“photoSearch”表,它已经存在 - 这不是我的应用程序。如果我尝试加入这两个表以丢失第二个查询,我会丢失所有索引,导致很长时间 - 所以我不能使用全文连接。这似乎是最快捷的方法。如果不是全文和加入问题,我会将这两个问题结合起来。
答案 0 :(得分:4)
这是事情。首先,获取你的照片ID并使mysql认为这是一个只保存照片ID的实际表格,然后制作你的实际声明,不需要任何额外的记录集连接......
不要忘记从最后开始做到这一点。以下是带有解释的示例代码:
第1步创建照片ID查找表并将其命名:这将是我们的PhotoId查找表,因此将其命名为“PhotoIds”
SELECT photoID FROM photoSearch
WHERE MATCH (headline, caption, people, keywords)
AGAINST ('"&booleanSearchStr&"' IN BOOLEAN MODE)
AND dateCaptured BETWEEN '"&fromDate&"' AND '"&toDate&"' LIMIT 0,50) AS PhotoIds
第2步现在我们有了照片ID,因此请从中获取信息。我们将在WHERE子句之前插入上面的语句,就像我们使用真实表一样。请注意,我们的“假”表必须介于parantheses之间。
SQL = "SELECT p.photoID, p.setID, p.eventID, p.locationID, p.headline, p.caption, + more FROM
photos AS p,
events AS e USING (p.eventID),
location AS l USING (p.locationID),
(SELECT photoID FROM photoSearch WHERE MATCH (headline, caption, people, keywords)
AGAINST ('"&booleanSearchStr&"' IN BOOLEAN MODE) AND dateCaptured BETWEEN
'"&fromDate&"' AND '"&toDate&"' LIMIT 0,50) AS PhotoIds
WHERE p.photoID=PhotoIds.photoID;"
注意:我只是在这里编写这些代码而从未测试过。可能存在一些拼写错误或smt。如果您有麻烦,请告诉我。
现在回答您的主要问题
无需关闭已执行的查询,尤其是在使用执行方法时。执行方法在执行后自行关闭,除非它没有返回任何记录集数据(这就是首先执行命令的目的),如:“INSERT”,“DELETE”,“UPDATE”。如果你没有打开记录集对象,那么为什么要尝试关闭从未打开的东西?相反,您可以使用设置Rs = Nothing 来取消对象的引用并发送到垃圾收集以释放一些系统资源(这与mysql本身无关)。如果您正在使用“SELECT”查询(将返回某些数据的查询),您必须打开一个记录集对象(ADODB.Recordset),如果您打开它,则需要在完成其工作后立即将其关闭。
最重要的是在每次加载页面后关闭“与mysql服务器的主连接”。 所以你可以考虑把你的连接关闭算法(不是记录集) (关闭)一个包含文件,并将其插入到您连接到数据库的每个页面的末尾。简短说明:如果您使用打开()
,则必须使用关闭()答案 1 :(得分:3)
如果你向我们展示你的SQL语句,也许我们可以告诉你如何将它们组合成一个单独的SQL语句,这样你只需要做一个循环,否则,像这样的双循环确实会对服务器性能产生影响。但在我学习存储过程和连接之前,我可能会这样做:
Set Conn = Server.CreateObject("Adodb.Connection")
Conn.Open "ConnectionString"
Set oRS = Server.CreateObject("Adodb.Recordset")
oRS.Open "SQL STATEMENT", Conn
Set oRS2 = Server.CreateObject("Adodb.Recordset")
oRS2.ActiveConnection = Conn
Do Until oRS.EOF
oRS2.Open "SQL STATEMENT"
If oRS2.EOF Then ...
oRS2.Close
oRS.Movenext
Loop
oRS.Close
Set oRS = Nothing
Set oRS2 = Nothing
Set Conn = Nothing
答案 2 :(得分:0)
我尝试将其放在评论中,因为它没有直接回答您的原始问题,但它太长了.. :)
您可以尝试使用子查询而不是连接,将外部查询嵌套在第二个查询中。 “...其中photoID在哪里(从photoSearch中选择photoID ......)”。不确定它是否会获得更好的结果,但它可能值得尝试。话虽这么说,全文搜索的使用确实改变了查询的优化方式,因此可能需要做更多的工作才能弄清楚适当的索引是什么(需要)。根据您现有的表现,可能不值得付出努力。
您是否确定此现有代码/查询是当前的瓶颈?有时我们花时间优化我们认为的事情是可能不是这样的瓶颈...... :)
另外一个想法 - 您可能需要考虑一些缓存逻辑来减少您可能正在进行的冗余查询量 - 无论是在页面级别还是在此方法级别。搜索参数可以连接在一起以形成用于将数据存储在某种高速缓存中的密钥。当然,您需要处理适当的缓存失效/到期逻辑。我已经看到系统速度提高了100倍,并且非常简单的缓存逻辑被添加到这样的瓶颈中。