经典ASP-何时关闭记录集



我想知道,在我的情况下,以下哪个示例最适合关闭记录集对象?

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问题的人(第二个查询),这里是:

这是一个在线照片库。我有两张桌子;"照片搜索"one_answers"照片"。第一个是"照片搜索",只有几列,包含照片的所有可搜索数据,如"照片ID"、"标题"、"说明"、"人物"、"dateCaptured"one_answers"关键字"。它有一个多列全文索引(标题、标题、人物、关键字)。第二个表"照片"包含所有的照片数据;高度、宽度、版权、标题、ID、日期等等。两者都有500K以上的行,标题和标题字段有时返回2000K以上的字符。

查询现在大致是这样的:(需要注意的是:我不能在全文搜索中使用联接,因此关键字存储在一列中-在"去规范化"表中。此外,这种伪代码和我的应用程序代码在其他地方-但它很接近)

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"上设置全文索引,而不是大表"photos",似乎在一定程度上提高了速度。我没有添加"照片搜索"表,它已经在那里了——这不是我的应用程序。如果我尝试连接这两个表以丢失第二个查询,那么我的索引将全部丢失,导致时间非常长,因此我不能将连接与全文一起使用。这似乎是最快的方法。如果不是因为全文和连接问题,我可能已经将这两个查询合并在一起了。

事情是这样的。首先,获取你的照片ID,让mysql认为这是一个只包含照片ID的实际表,然后做出你的实际声明,不需要任何额外的记录集连接。。。

不要忘记从头开始做这件事。以下是带有说明的示例代码:

步骤1创建照片ID查找表并命名:这将是我们的照片ID查找表格,因此将其命名为"照片ID"

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子句之前插入上述语句,方法与处理真实表相同。请注意,我们的"假"表必须介于副题之间。

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。如果你有麻烦,请告诉我。

现在得到您的主要问题

无需关闭已执行的查询,尤其是当您使用execute方法时。Execute方法在执行后关闭自己,除非它不返回任何记录集数据(这是执行命令的目的),如:"INSERT"、"DELETE"、"UPDATE"。如果您没有打开记录集对象,那么为什么要关闭从未打开过的对象呢?相反,您可以使用Set Rs=Nothing取消引用对象并将其发送到垃圾收集以释放一些系统资源(这与mysql本身无关)。如果使用"SELECT"查询(将返回一些数据的查询),则必须打开一个记录集对象(ADODB.recordset),如果打开了它,则需要在它完成作业后立即关闭它。

最重要的是在每次页面加载后关闭"与mysql服务器的主连接"因此,您可以考虑将连接关闭算法(而不是记录集关闭)放在包含文件中,并将其插入到连接到数据库的每个页面的末尾。长话短说:如果你使用Open()

,你必须使用Close()

如果你向我们展示你的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

我试着把它放在评论中,因为它不能直接回答你最初的问题,但它太长了..:)

您可以尝试使用子查询而不是联接,将外部查询嵌套在第二个查询中。"…其中photoID在(从photoSearch中选择photoID…)"。不确定它是否会得到更好的结果,但它可能值得一试。也就是说,全文搜索的使用确实改变了查询的优化方式,因此可能需要更多的工作来确定合适的索引(需要)。根据你现有的表现,这可能不值得付出努力。

你确定这个现有的代码/查询是当前的瓶颈吗?有时我们会花时间优化我们认为是瓶颈的事情,但事实并非如此…:)

另外一个想法是,您可能需要考虑一些缓存逻辑,以减少可能进行的冗余查询的数量,无论是在页面级别还是在该方法级别。搜索参数可以连接在一起,形成将数据存储在某种缓存中的密钥。当然,您需要处理适当的缓存无效/到期逻辑。我看到系统的速度提高了100倍,在这样的瓶颈中添加了非常简单的缓存逻辑。

只需询问记录集的状态是1还是0,这意味着打开或关闭

像这个

If RS.State = 1 Then RS.Close
 

与数据库(CN)的连接仍将打开,但您可以使用任何值

重新打开RS(记录集)

最新更新