MySQL版本:5.5.37-0Ubuntu0.14.04.1
我目前正在编写一个python脚本,它利用许多mysql表和查询从存储在表中的反向索引中获取结果。
我注意到,在执行查询时,在mysqldb python模块中选择正确的光标类型对性能有很大的影响,我想知道是否有人可以解释或提供可靠的资源来解释何时使用哪个光标。
例如,使用sscursor执行此查询40次需要7秒:
SELECT Pages.PageID,
Pages.PageName,
Counter AS TermFreq,
Pages.Length,
(Counter / LOG(Length)) AS Weight
FROM Pages
INNER JOIN TermOccurrences ON TermOccurrences.PageID = Pages.PageID
INNER JOIN Terms ON TermOccurrences.TermID = Terms.TermID
WHERE TermName = %s
ORDER BY Weight DESC
LIMIT 20;
使用默认光标运行同一查询40次需要0.004秒。
但是,删除权重(counter/log(length))的计算会使该查询使用sscursor再次快速执行。
我之所以使用sscursor,是因为它在许多其他查询上都表现得非常出色,然后突然变得非常慢。当它执行得如此之快时,改回默认光标让我吃惊。
编辑:
还有一些例子。
使用默认光标运行以下命令40次需要~3秒:
SELECT COUNT(*)
FROM Pages
INNER JOIN TermOccurrences ON TermOccurrences.PageID = Pages.PageID
INNER JOIN Terms ON TermOccurrences.TermID = Terms.TermID
WHERE TermName = %s AND Counter > 2
用sscursor运行它需要大约0.002秒。
最佳答案
MySQLdb docs提到标准光标类使用的是mysql_store_result()
,而sscursor使用的是mysql_use_result()
“,后者必须确保在执行另一个查询之前读取了所有行”。
所以这是关于mysql_store_result()
和mysql_use_result()
的。
MySQL docs提到mysql_use_result()
启动结果集检索,而不实际将结果集读取到客户机中,就像mysql_store_result()一样。因此,必须通过调用mysql_fetch_row()
来单独检索每一行,当然,在处理大型表时,这些调用会大大增加。
同样在mysqldb文档中:
“服务器端”光标。与光标类似,但使用
CursorUserResultMixin。仅当您正在处理潜在的
大型结果集。
因此,如果您的结果集太大而无法同时移动到您的客户机中,SSCursor
主要是好的。
另请参见以下问题:
How to efficiently use MySQLDB SScursor?
MySQLdb is extremely slow with large result sets
请注意,LIMIT 20
查询永远不会这么大。你可能要检查你的钥匙。为了更好地理解为什么这可能需要7秒钟,最好在一个问题中也包括db模式,可能还有更多关于DBA stack的内容。