Python 中的 MySQL 查询速度较慢,但​​在其他地方速度较快

Posted

技术标签:

【中文标题】Python 中的 MySQL 查询速度较慢,但​​在其他地方速度较快【英文标题】:Slow MySQL queries in Python but fast elsewhere 【发布时间】:2013-07-16 01:06:04 【问题描述】:

我在处理 Python 中缓慢的 mysql 查询时遇到了麻烦。在我的应用程序的一个区域中,“加载数据文件”很快。在另一个领域,选择查询非常慢。

phpMyAdmin 和 Navicat 中执行相同的查询(作为第二次测试)产生的响应速度比 Python 快约 5 倍。

一些笔记...

我切换到 MySQLdb 作为连接器,并且还在使用 SSCursor。性能没有提升。 数据库已经过优化、索引等。我正在将此应用程序从 PHP/Codeigniter 移植到 Python 并运行良好(我愚蠢地认为退出 PHP 会有助于加快速度) PHP/Codeigniter 快速执行选择查询。例如,应用程序的一个关键方面在 PHP/Codeigniter 中大约需要 2 秒,但在 Python 中需要 10 秒才能完成任何数据分析。

我的数据库链接是相当标准的...

dbconn=MySQLdb.connect(host="127.0.0.1",user="*",passwd="*",db="*", cursorclass = MySQLdb.cursors.SSCursor)

任何见解/帮助/建议将不胜感激!

更新

在获取/处理结果方面,我尝试了几种方法。初始查询是相当标准的...

# Run Query
cursor.execute(query)

我删除了这个循环中的所有代码,只是为了确保它不是瓶颈问题,事实并非如此。我把虚拟代码放在它的位置。整个过程一点都没有加快。

db_results = "test"

# Loop Results
for row in cursor:

    a = 0 (this was the dummy code I put in to test)

return db_results

查询结果本身只有 501 行(大量列)...在 Python 之外花费了 0.029 秒。比 Python 中花费的时间要长得多。

该项目与赛马有关。查询在此函数中完成。查询本身很长,但是,它在 Python 之外运行良好。我故意注释掉循环中的代码以进行测试......还有 print(query) 希望弄清楚这一点。

# Get PPs
def get_pps(race_ids):

# Comma Race List
race_list = ','.join(map(str, race_ids))

# PPs Query
query = ("SELECT raceindex.race_id, entries.entry_id, entries.prognum, runlines.line_id, runlines.track_code, runlines.race_date, runlines.race_number, runlines.horse_name, runlines.line_date, runlines.line_track, runlines.line_race, runlines.surface, runlines.distance, runlines.starters, runlines.race_grade, runlines.post_position, runlines.c1pos, runlines.c1posn, runlines.c1len, runlines.c2pos, runlines.c2posn, runlines.c2len, runlines.c3pos, runlines.c3posn, runlines.c3len, runlines.c4pos, runlines.c4posn, runlines.c4len, runlines.c5pos, runlines.c5posn, runlines.c5len, runlines.finpos, runlines.finposn, runlines.finlen, runlines.dq, runlines.dh, runlines.dqplace, runlines.beyer, runlines.weight, runlines.comment, runlines.long_comment, runlines.odds, runlines.odds_position, runlines.entries, runlines.track_variant, runlines.speed_rating, runlines.sealed_track, runlines.frac1, runlines.frac2, runlines.frac3, runlines.frac4, runlines.frac5, runlines.frac6, runlines.final_time, charts.raceshape "
         "FROM hrdb_raceindex raceindex "
         "INNER JOIN hrdb_runlines runlines ON runlines.race_date = raceindex.race_date AND runlines.track_code = raceindex.track_code AND runlines.race_number = raceindex.race_number "
         "INNER JOIN hrdb_entries entries ON entries.race_date=runlines.race_date AND entries.track_code=runlines.track_code AND  entries.race_number=runlines.race_number AND entries.horse_name=runlines.horse_name "
         "LEFT JOIN hrdb_charts charts ON runlines.line_date = charts.race_date AND runlines.line_track = charts.track_code AND runlines.line_race = charts.race_number "
         "WHERE raceindex.race_id IN (" + race_list  + ") "
         "ORDER BY runlines.line_date DESC;")

print(query)

# Run Query
cursor.execute(query)

# Query Fields
fields = [i[0] for i in cursor.description]

# PPs List
pps = []

# Loop Results
for row in cursor:

    a = 0
    #this_pp = 

    #for i, value in enumerate(row):
    #    this_pp[fields[i]] = value            

    #pps.append(this_pp)

return pps

最后一点...我还没有考虑过处理结果的理想方法。我相信一个光标允许结果作为一组字典返回。我什至还没有做到这一点,因为查询和返回本身太慢了。

【问题讨论】:

这通常不是 sql 问题,而是您如何获取和处理结果的问题。几行代码将帮助 pythonite 追踪它 可以切换回普通游标重新检查查询执行速度吗? 我认为,正常光标是最初的原因。两者都产生了同样缓慢的结果。 MySQL 有两个 Python 提供程序。试试其他的。 如果没有更多周围的 Python 代码,就不可能在这里提供任何真正的输入。看起来你可能有一点不太正确,但看不到它,没人能说。 【参考方案1】:

虽然您只有 501 行,但看起来您有超过 50 列。有多少总数据从 MySQL 传递到 Python?

501 行 x 55 列 = 返回 27,555 个单元格。

如果每个单元格平均“仅”1K,则返回的数据接近 27MB。

要了解 mysql 推送了多少数据,您可以将其添加到查询中:

SHOW SESSION STATUS LIKE "bytes_sent"

您的服务器资源充足吗?内存分配配置好了吗?

我的猜测是,当您使用 PHPMyAdmin 时,您会得到分页结果。这掩盖了 MySQL 返回的数据超出服务器处理能力的问题(我不使用 Navicat,不确定返回结果的方式)。

也许 Python 进程是内存受限的,当面对如此大的结果集时,它必须将分页输出到磁盘以处理结果集。

如果您在查询中减少调用和/或限制到的列数,例如LIMIT 10,您的速度会提高吗?

当调用这个查询时,你能看到运行 Python 的服务器是否正在分页到磁盘?你能看到为 Python 分配了哪些内存,在此过程中使用了多少,以及与 PHP 版本中的相同值相比,分配和使用情况如何?

您能否为受限资源分配更多内存?

能否减少通过分页或异步加载调用的列数或行数?

【讨论】:

感谢您的反馈。在设置方面...全新机器,64g RAM,重量级处理器等。我会尝试减少结果计数,但无论如何运行这么慢感觉就像一场灾难。我会回来报告的。谢谢! MySQL 和 Python 是否在同一台服务器上? MySQL 和 PHP 是否在同一台服务器上? 是的,它们都在同一台机器上。机器也很咸...... 64g ram等。 关于我的回答中提出的问题的任何新报告?【参考方案2】:

我知道这已经晚了,但是,我在 mysql 和 python 上遇到了类似的问题。我的解决方案是使用另一种语言的查询...我使用 R 来进行快速查询,在 R 中尽我所能,然后将数据发送到 python,如果需要进行更通用的编程,尽管 R 有很多通用的目的库也是如此。只是想发布一些可能对遇到类似问题的人有所帮助的东西,我知道这一步是问题的核心。

【讨论】:

以上是关于Python 中的 MySQL 查询速度较慢,但​​在其他地方速度较快的主要内容,如果未能解决你的问题,请参考以下文章

与从 CSV 文件导出和导入相比,Python MySQLdb SScursor 速度较慢。可以加速吗?

前端面试题

没有返回任何内容时,SQL Server 查询运行速度较慢

当 MDX 查询包含 2 个或更多级别的相同维度时,速度较慢

基于 mysql 视图结果创建表以加快获取速度

MySQL之索引