pd.read_sql 某些类型的第一次查询速度慢
pd.read_sql slow for first query of certain type
当我将某些类型的 SQL 查询中的数据读入 pandas 数据帧时,我 运行 遇到了性能问题。我首先使用如下代码在 Azure 中查询 SQL 数据库:
cnxn = pyodbc.connect(db_conn_str)
starttime = timeit.default_timer()
sql = "Select * from table where var1 != 'a' and var2 = 'b' and var3 = 'c' and var4 = 'd'"
outdata = pd.read_sql(sql, cnxn)
print("Elapsed time :", timeit.default_timer() - starttime)
这通常需要大约 20-30 秒。如果我重新运行 上面的查询,或者如果我 运行 另一个查询,其中 'a'、'b'、'c' 和 'd' 在接下来20分钟左右,查询只需要0.5秒左右。 20 分钟后,下一次此类查询将需要 20-30 秒。
其他类型的查询需要更短的时间(例如,我只限制使用 var2 的查询)并且我已经尝试先 运行ning 这些查询,但是使用上面代码的第一个查询仍然需要 20 -30 秒。
我想这与 SQL 数据库有关?有人可以解释为什么我会看到这种情况吗?有什么方法可以防止第一个查询花费更长的时间吗?
对于此查询:
select *
from table
where var1 <> 'a' and var2 = 'b' and var3 = 'c' and var4 = 'd'
我会推荐 (var2, var3, var4, var1)
上的索引。然后查询将使用此索引来查找所需的行。如果结果集很大,查询仍然需要很长时间。
也就是说,您面临的问题听起来像是 "cold cache" 问题。您不指定数据库,但通常情况下,数据库开始时内存中没有数据。当您获取数据页或索引页时,数据库会将它们缓存在内存中,以便后续访问更快。
正如 Gordon 指出的那样,索引很重要,您需要解决 SQL 语句中的冲突。你是这个意思吗?
sql = "Select * from table where var1 != 'a' and var2 = 'b' and (var3 = 'c' OR var3 = 'd')"
此外,最好考虑一下您是否需要所有这些语句。有多少行 var1 是 a,var2 不是 b,var3 不是 c 或 d?如果它是一个非常小的数字,您可能需要考虑在您的代码中而不是在 SQL 语句中过滤结果。
有时您可以看到在 where 子句中使用子查询(WHERE var IN (a, b, c) AND var NOT IN (b, e))或通过选择单个列或计数(* ) 代替 *。
希望对您有所帮助:)
当我将某些类型的 SQL 查询中的数据读入 pandas 数据帧时,我 运行 遇到了性能问题。我首先使用如下代码在 Azure 中查询 SQL 数据库:
cnxn = pyodbc.connect(db_conn_str)
starttime = timeit.default_timer()
sql = "Select * from table where var1 != 'a' and var2 = 'b' and var3 = 'c' and var4 = 'd'"
outdata = pd.read_sql(sql, cnxn)
print("Elapsed time :", timeit.default_timer() - starttime)
这通常需要大约 20-30 秒。如果我重新运行 上面的查询,或者如果我 运行 另一个查询,其中 'a'、'b'、'c' 和 'd' 在接下来20分钟左右,查询只需要0.5秒左右。 20 分钟后,下一次此类查询将需要 20-30 秒。
其他类型的查询需要更短的时间(例如,我只限制使用 var2 的查询)并且我已经尝试先 运行ning 这些查询,但是使用上面代码的第一个查询仍然需要 20 -30 秒。
我想这与 SQL 数据库有关?有人可以解释为什么我会看到这种情况吗?有什么方法可以防止第一个查询花费更长的时间吗?
对于此查询:
select *
from table
where var1 <> 'a' and var2 = 'b' and var3 = 'c' and var4 = 'd'
我会推荐 (var2, var3, var4, var1)
上的索引。然后查询将使用此索引来查找所需的行。如果结果集很大,查询仍然需要很长时间。
也就是说,您面临的问题听起来像是 "cold cache" 问题。您不指定数据库,但通常情况下,数据库开始时内存中没有数据。当您获取数据页或索引页时,数据库会将它们缓存在内存中,以便后续访问更快。
正如 Gordon 指出的那样,索引很重要,您需要解决 SQL 语句中的冲突。你是这个意思吗?
sql = "Select * from table where var1 != 'a' and var2 = 'b' and (var3 = 'c' OR var3 = 'd')"
此外,最好考虑一下您是否需要所有这些语句。有多少行 var1 是 a,var2 不是 b,var3 不是 c 或 d?如果它是一个非常小的数字,您可能需要考虑在您的代码中而不是在 SQL 语句中过滤结果。
有时您可以看到在 where 子句中使用子查询(WHERE var IN (a, b, c) AND var NOT IN (b, e))或通过选择单个列或计数(* ) 代替 *。
希望对您有所帮助:)