Postres/Python - 使用一个大查询好还是几个小查询好?您如何决定要包含在 'WHERE IN' 子句中的项目数?
Postres/Python - is it better to use one large query, or several smaller ones? How do you decide number of items to include in 'WHERE IN' clause?
我正在编写一个 Python 脚本,它将 运行 在效率是关键的生产环境中定期执行。
下面是我的匿名查询,它提取了 3,000 种不同商品的销售数据。
我 认为 我一次查询所有结果时速度变慢。当我尝试查询不同的尺寸时,所花费的时间变化不一致(可能是由于我的互联网连接)。例如,有时查询 1000 个项目 3 次比一次查询所有 3000 个要快。但是,运行5 分钟后进行相同的测试得到了不同的结果。它是一个生产数据库,性能可能取决于当前流量。我不是数据库管理员,但从事数据科学工作,主要使用类似的 select 查询(我在 Python 中完成其余工作)。
这里有最佳实践吗?某种逻辑决定在 WHERE IN 子句中放入多少项?
date_min = pd.to_datetime('2021-11-01')
date_max = pd.to_datetime('2022-01-31')
sql = f"""
SELECT
product_code,
sales_date,
n_sold,
revenue
FROM
sales_daily
WHERE
product_code IN {tuple(item_list)}
and sales_date >= DATE('{date_min}')
and sales_date <= DATE('{date_max}')
ORDER BY
sales_date DESC, revenue
"""
df_act = pd.read_sql(sql, di.db_engine)
df_act
如果您的 sales_date
列已在数据库中建立索引,我认为在 where 子句 (DATE
) 中使用函数可能会导致计划不使用该索引。我相信如果将 date_min
和 date_max
作为字符串 (YYYY-MM-DD) 连接到 SQL 字符串中并去掉该函数,您的运气会更好。另外,使用 BETWEEN...AND
而不是 >= ... AND ... <=
.
至于 IN
有 1000 个项目,强烈建议您不要这样做。创建这些值的 single-column temp table 并为项目编制索引,然后加入 product_code.
一般来说,是这样的:
DROP TABLE IF EXISTS _item_list;
CREATE TEMP TABLE _item_list
AS
SELECT item
FROM VALUES (etc) t(item);
CREATE INDEX idx_items ON _item_list (item);
SELECT
product_code,
sales_date,
n_sold,
revenue
FROM
sales_daily x
INNER JOIN _item_list y ON x.product_code = y.item
WHERE
sales_date BETWEEN '{date_min}' AND '{date_max}'
ORDER BY
sales_date DESC, revenue
作为附录,尝试让项目列表中的项目与 product_code 上的索引顺序相同。
我正在编写一个 Python 脚本,它将 运行 在效率是关键的生产环境中定期执行。
下面是我的匿名查询,它提取了 3,000 种不同商品的销售数据。
我 认为 我一次查询所有结果时速度变慢。当我尝试查询不同的尺寸时,所花费的时间变化不一致(可能是由于我的互联网连接)。例如,有时查询 1000 个项目 3 次比一次查询所有 3000 个要快。但是,运行5 分钟后进行相同的测试得到了不同的结果。它是一个生产数据库,性能可能取决于当前流量。我不是数据库管理员,但从事数据科学工作,主要使用类似的 select 查询(我在 Python 中完成其余工作)。
这里有最佳实践吗?某种逻辑决定在 WHERE IN 子句中放入多少项?
date_min = pd.to_datetime('2021-11-01')
date_max = pd.to_datetime('2022-01-31')
sql = f"""
SELECT
product_code,
sales_date,
n_sold,
revenue
FROM
sales_daily
WHERE
product_code IN {tuple(item_list)}
and sales_date >= DATE('{date_min}')
and sales_date <= DATE('{date_max}')
ORDER BY
sales_date DESC, revenue
"""
df_act = pd.read_sql(sql, di.db_engine)
df_act
如果您的 sales_date
列已在数据库中建立索引,我认为在 where 子句 (DATE
) 中使用函数可能会导致计划不使用该索引。我相信如果将 date_min
和 date_max
作为字符串 (YYYY-MM-DD) 连接到 SQL 字符串中并去掉该函数,您的运气会更好。另外,使用 BETWEEN...AND
而不是 >= ... AND ... <=
.
至于 IN
有 1000 个项目,强烈建议您不要这样做。创建这些值的 single-column temp table 并为项目编制索引,然后加入 product_code.
一般来说,是这样的:
DROP TABLE IF EXISTS _item_list;
CREATE TEMP TABLE _item_list
AS
SELECT item
FROM VALUES (etc) t(item);
CREATE INDEX idx_items ON _item_list (item);
SELECT
product_code,
sales_date,
n_sold,
revenue
FROM
sales_daily x
INNER JOIN _item_list y ON x.product_code = y.item
WHERE
sales_date BETWEEN '{date_min}' AND '{date_max}'
ORDER BY
sales_date DESC, revenue
作为附录,尝试让项目列表中的项目与 product_code 上的索引顺序相同。