如何加快包含 sql 查询的代码?
Posted
技术标签:
【中文标题】如何加快包含 sql 查询的代码?【英文标题】:How can I speed up the code that contains the sql query? 【发布时间】:2020-05-30 12:41:04 【问题描述】:我的数据框包含大约 650,000 个唯一行。对于每一行,我需要从数据库中获取一个值。我使用 for 循环,但执行时间非常长,大约 25 小时。如何加快代码执行速度?我假设您需要使用 joblib 或 numba 并行化执行。但是循环体中存在的 sql 查询令人困惑。
for x in tqdm_notebook(range(len(table))):
good = table.iloc[x, 0]
store = table.iloc[x, 1]
start = table.iloc[x, 6]
query = f"""
SELECT
good_id,
store_id,
AVG(sale) AS avg_sale,
SUM(sale) AS sum_sale,
MAX(sale) AS max_sale,
MIN(sale) AS min_sale
FROM my_table
WHERE good_id = good
AND store_id = store
AND date_id BETWEEN DATEADD(MONTH, -2, 'start') AND DATEADD(MONTH, -1, 'start')
GROUP BY good_id, store_id
"""
temp = pd.read_sql(query, connection)
if not temp.empty:
table.iloc[x, 13] = temp['avg_sale'].values
table.iloc[x, 14] = temp['sum_sale'].values
table.iloc[x, 15] = temp['max_sale'].values
table.iloc[x, 16] = temp['min_sale'].values
【问题讨论】:
因为您使用的是 Python 格式字符串而不是 read_sql() with a parameterized query,所以每次迭代都会有不同的 SQL 语句并会导致查询编译命中。 my_table 是否有关于 good_id、store_id、date_id 的覆盖索引? 表有列存储,大小约为10亿行。 无论如何我都会放弃在这里进行 650,000 个单独查询的想法。如果你必须这样做,你至少应该在good_id,store_id, date_id INCLUDE (Sale)
上有一个索引。仅仅依靠列存储意味着每次都会读取所有行。
【参考方案1】:
为此,您可以扩大查询范围并获取所有 (store,good,day) 元组,获取这些元组的部分聚合,然后在 pandas 中执行最终过滤和聚合。请注意,您将 AVG
更改为 COUNT(*)
并在最终聚合中计算 AVG。
将参数列表传递给 SQL Server 的一种便捷方法是使用OPENJSON。只需发送一个带有 JSON 标量数组的字符串参数,例如
'[123,324,445,23,1322]'
或
'["abd","def","d"]'
类似
SELECT
good_id,
store_id,
date_id,
count(*) AS count_sale.
SUM(sale) AS sum_sale,
MAX(sale) AS max_sale,
MIN(sale) AS min_sale
FROM my_table
WHERE good_id in (select cast(value as int) from openjson(?))
AND store_id in (select cast(value as int) from openjson(?))
AND date_id BETWEEN ? and ?
GROUP BY good_id, store_id, date_id
ORDER BY good_id, store_id, date_id
【讨论】:
以上是关于如何加快包含 sql 查询的代码?的主要内容,如果未能解决你的问题,请参考以下文章
如何加快在 2500 万行上还包含 JOIN 的 SQL UPDATE