- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
如何从速度的角度改进以下功能?理想情况下,我希望将 executemany 用作此向上过程的一部分。
虽然该功能工作正常,但我确信有更有效的方法来做到这一点;检查值是否存在并根据需要更新/插入。
我需要每天对数百万数据执行此操作。
def insert_or_update(self, profile_id, landing_page, keyword, position, impressions, clicks, ctr):
''' checks if a entry exists, if not it's inserted. If it is, the metrics
are updated.
'''
try:
self.cursor.execute('select id, position, impressions, clicks, ctr from temp where profile_id={} and keyword="{}" and landing_page="{}"'.format(profile_id, keyword, landing_page))
data = self.cursor.fetchone()
if data:
row_id = data[0]
sql_impressions = data[2] + impressions
sql_clicks = data[3] + clicks
sql_ctr = sum([data[4], ctr]) / len([data[4], ctr])
# if the keyword/landing_page exists
self.cursor.execute("update temp set position={}, impressions={}, clicks={}, ctr={} where id={}".format(position, sql_impressions, sql_clicks, sql_ctr, row_id))
# Commit your changes in the database
self.db.commit()
return self.cursor.lastrowid
else:
# if the keyword/landing_page doesn't exist
self.cursor.execute("insert into temp (profile_id, landing_page, keyword, position, impressions, clicks, ctr) values (%s, %s, %s, %s, %s, %s, %s)", (profile_id, landing_page, keyword, position, impressions, clicks, ctr))
# Commit your changes in the database
self.db.commit()
return self.cursor.lastrowid
except Exception as e:
return e
# Rollback in case there is any error
self.db.rollback()
finally:
self.db.close()
最佳答案
如果您需要执行此操作数百万次,则会出现大量性能问题。
您正在一遍又一遍地准备相同的 SQL 语句,数百万次。准备一次并执行数百万次会更好。
您在单个查询后的每个函数调用中都断开了与数据库的连接。这意味着您每次都需要重新连接,并且所有缓存的信息都会被丢弃。不要那样做,保持连接状态。
您在每一行之后都做出了 promise 。这会减慢速度。相反,在完成一批后提交。
选择 + 更新或插入可能可以作为单个更新插入来完成。
您向临时表中插入这么多内容可能是性能问题。
如果表中的索引太多会减慢插入速度。有时最好删除索引,进行大批量更新,然后重新创建它们。
因为您将值直接放入 SQL 中,所以您的 SQL 对 SQL injection attack 开放.
相反...
UPDATE
而不是 SELECT + math + UPDATE
中完成所有数学运算。SELECT
,然后使用UPDATE
或INSERT
首先,准备语句。这些让 MySQL 编译语句一次,然后重新使用它。这个想法是你写一个带有值占位符的语句。
select id, position, impressions, clicks, ctr
from temp
where profile_id=%s and
keyword=%s and
landing_page=%s
然后将值作为参数而不是字符串的一部分执行。
self.cursor.execute(
'select id, position, impressions, clicks, ctr from temp where profile_id=%s and keyword=%s and landing_page=%s',
(profile_id, keyword, landing_page)
)
这允许数据库缓存准备好的语句,而不必每次都重新编译它。它还避免了 SQL 注入(inject)攻击,在这种情况下,聪明的攻击者可以制作一个实际上更像 SQL 的值,如 "MORE SQL HERE "
。这是一个非常、非常、非常普遍的安全漏洞。
请注意,您可能需要使用 MySQL's own Python database library to get true prepared statements .不要太担心,使用准备好的语句不是你最大的性能问题。
接下来,您基本上要做的是添加到现有行,或者如果没有现有行,则插入一个新行。使用 UPSERT
、INSERT
和 UPDATE
的组合,可以在单个语句中更有效地完成此操作。 MySQL has it as INSERT ... ON DUPLICATE KEY UPDATE
.
要查看这是如何完成的,我们可以将您的 SELECT then UPDATE
编写为单个 UPDATE
。计算在 SQL 中完成。
update temp
set impressions = impressions + %s,
clicks = clicks + %s,
ctr = (ctr + %s / 2)
where profile_id=%s and
keyword=%s and
landing_page=%s
您的 INSERT 保持不变...
insert into temp
(profile_id, landing_page, keyword, position, impressions, clicks, ctr)
values (%s, %s, %s, %s, %s, %s, %s)
将它们组合成一个 INSERT ON DUPLICATE KEY UPDATE。
insert into temp
(profile_id, landing_page, keyword, position, impressions, clicks, ctr)
values (%s, %s, %s, %s, %s, %s, %s)
on duplicate key update
update temp
set impressions = impressions + %s,
clicks = clicks + %s,
ctr = (ctr + %s / 2)
这取决于表的键被定义为什么。如果您有 unique( profile_id, landing_page, keyword )
那么它应该与您的代码一样工作。
即使您不能执行 upsert,您也可以通过尝试 UPDATE
来消除 SELECT
,检查它是否更新了任何内容,如果它没有执行一个 INSERT
。
批量更新。与其调用执行一次更新和提交的子例程,不如将一大堆要更新的内容传递给它并在循环中处理它们。您甚至可以利用 executemany
运行具有多个值的相同语句。然后提交。
您可以批量执行 UPSERT
。 INSERT
可以一次获取多行。例如,这将插入三行。
insert into whatever
(foo, bar, baz)
values (1, 2, 3),
(4, 5, 6),
(7, 8, 9)
您可以对 INSERT ON DUPLICATE KEY UPDATE
执行相同的操作,从而减少与数据库对话的开销。参见 this post for an example (在 PHP 中,但您应该能够适应)。
这牺牲了返回最后插入行的 ID,但它们是中断。
关于python - 加快 MySQL 更新/插入语句,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41092110/
我想使用 ffmpeg 框架更改视频速度。我为此使用了这个命令: ffmpeg -y -i /storage/extSdCard/Video/1.avi -filter_complex [0:v]fp
我有以下数据数组,有 200 万个条目: [20965 1239 296 231 -1 -1 20976 1239 299 314 147 337 255
我正在使用 Oracle 数据库,并且想获取一个包含 3000 万条记录的表。 library(RODBC) ch <- odbcConnect("test", uid="test_user",
我在 android 上使用 FFmpeg 来: 1- 合并 3 个视频 2-添加音频 3-添加标志 4-修剪 3 个视频之一 5-改变输出的fps 我已经实现了正确的代码,但花了 30 分钟。对于(
我使用 GLPKMathProgInterface 和 JuMP 编写了一个程序来解决 Julia 中的线性程序。 Julia 代码由 python 程序调用,该程序通过多个命令行调用运行多个 Jui
我们使用 POV-Ray 每次运行生成大约 80 张图像,我们将这些图像拼接在一起形成两个移动的 GIF 文件(一个场景的两个 360 度 View )。我们正在寻找尽可能加快此镜像创建的方法(在 h
就目前情况而言,这个问题不太适合我们的问答形式。我们希望答案得到事实、引用资料或专业知识的支持,但这个问题可能会引发辩论、争论、民意调查或扩展讨论。如果您觉得这个问题可以改进并可能重新开放,visit
我将数据从一个数据库插入到另一个数据库,所以我有 2 个连接(Conn1 和 Conn2)。下面是代码(使用pypyodbc)。 import pypyodbc Conn1_Query = "SE
在我的应用程序中,我显示 EKEvents 列表,我想在 UITableView 中显示一个月的所有事件,每个部分包含各自的日期。嗯,这可行,我得到了我需要的所有数据,但获取速度非常慢。 问题在于事件
我有一个移动速度非常慢的传送带。我不知道什么JS脚本控制速度,我需要它来加速。无法从主题制作者那里获得任何帮助。任何建议都会非常有帮助。谢谢 页面: http://krankgolf2017.wpen
有没有办法加快这段代码的速度?我需要它来删除相同的内容并将其写入单元格,以强制其他 VBA 代码运行另一列上的代码。这就是它的作用,只是 super 慢。有时此表上有 2000 个条目/行。每个单元大
我正在开发一个相当大的程序,它再次从一个相当大的 Excel 电子表格中获取数据。由于一些奇怪的原因,加载这个大的 Excel 文件需要很长时间,我希望能以某种方式加快速度。我做了自己的研究并尝试了
我有下面的代码,将所有按钮(有 10 个)着色为灰色,以清除任何先前着色的按钮,然后将所选按钮着色为蓝色。基本上充当当前选择哪个按钮的指示器。我注意到代码现在需要一些时间才能通过这种修饰添加来运行,我
我有一个 LINQ 查询,它正在搜索包含大约 250,000 条记录的 SQL 表,并且仅搜索 2 个字段。这两个字段都已建立索引,但我发现它的运行速度仍然相当慢。 下面是代码,有人可以提出任何建议来
对于相对较大的 Pandas DataFrame(几十万行),我想创建一个应用函数结果的系列。问题是该功能不是很快,我希望它能以某种方式加快速度。 df = pd.DataFrame({ 'valu
这个问题在这里已经有了答案: Faster weighted sampling without replacement (3 个答案) 关闭 9 年前。 如何在 R 中加快概率加权采样。 # Let
在运行 PhantomJS 提供的 rasterize.js 示例时,我发现我必须等待 20 秒或更长时间才能生成网页图像。 有没有可能在不消耗大量资源的情况下加快速度的方法?我基本上希望快速生成从加
我正在开发一个相当大的程序,它再次从一个相当大的 Excel 电子表格中获取数据。由于一些奇怪的原因,加载这个大的 Excel 文件需要很长时间,我希望能以某种方式加快速度。我做了自己的研究并尝试了
我有下面的代码,将所有按钮(有 10 个)着色为灰色,以清除任何先前着色的按钮,然后将所选按钮着色为蓝色。基本上充当当前选择哪个按钮的指示器。我注意到代码现在需要一些时间才能通过这种修饰添加来运行,我
我有一个 Excel 工作簿,用户通过单击按钮导入文本文件。我的代码完全按照我的需要工作,但是在填写 H 列“阅读日期”时速度非常慢。将文本文件导入 Excel 工作表后,我的 Excel 工作簿如下
我是一名优秀的程序员,十分优秀!