【问题标题】:Sqlite3 Module in Python far Slower SELECT than in ShellPython中的Sqlite3模块SELECT比Shell慢得多
【发布时间】:2014-05-06 11:25:35
【问题描述】:

我在 Python 中使用 sqlite3 模块,但我发现相对于在命令 shell 中在 sqlite3 中运行查询而言,某个 SELECT 查询的速度非常慢。我首先要说两个版本都是相同的 3.7.17。

我的查询是

SELECT r.ID, r.Date FROM my_table r
WHERE
r.Date IN (SELECT Date FROM my_table WHERE ID = r.ID GROUP BY Date LIMIT 2);

Python代码是

con = lite.connect(path_to_database)
cur = con.cursor()

with con:
    cur.execute(sql_query)

其中sql_query 是一个包含初始查询的字符串变量。

我假设问题在于优化 IN 子查询。

性能细节:my_table 包含 167000 条记录,shell 中的查询大约需要 10 秒,Python 中的查询需要 > 5 分钟(当它到达这里时我停止了它)。

目前由于是创建表,我只是将代码复制并粘贴到 shell 中作为一种解决方法,我该如何解决这个问题,以便我可以从 Python 运行查询?

添加

当我运行EXPLAIN QUERY PLAN 时,我得到以下信息

壳牌:

0           0           0           SCAN TABLE PIT_10_Days AS r (~500000 rows)
0           0           0           EXECUTE CORRELATED LIST SUBQUERY 1
1           0           0           SEARCH TABLE PIT_10_Days USING AUTOMATIC C
1           0           0           USE TEMP B-TREE FOR GROUP BY

Python:

0           0           TABLE PIT_10_Days AS r 
0           0           TABLE PIT_10_Days

我不确定差异是在 Python 中获取 EXPLAIN QUERY PLAN 的问题,还是实际上是问题本身。

【问题讨论】:

  • 您能向我们展示您用于查询的 Python 代码吗?用于测试的样本数据也会有所帮助。
  • 嗨 Jan,代码本身很长,但基本上是 con = sqlite3.connect(path_to_database); cur = con.curor(); with con: cur.execute(the_above_query)
  • 你能确认没有在 shell 中执行任何 PRAGMA 语句吗?
  • 我该怎么做?
  • @rwolst 请将您调用查询的方式添加到您的问题中,它将更具可读性。意识到,您谈论的是在shall中执行的相同查询,并且来自具有不同执行时间的Python。由于您只向我们显示查询,我们不知道上下文,这可能是问题的关键。

标签: python sql shell sqlite


【解决方案1】:

很抱歉这么晚了,但我现在才发现这个问题。
不幸的是,我不知道为什么 sqlite3 模块的行为与 shell 不同,但是 您可以尝试从一开始就避免相关查询。我不确定它是否总是做你想要的,因为你没有在你的子查询中对结果进行排序。

我想您想要每个 ID 的两个最新日期? 试试这个:

SELECT r.ID AS ID, max( r.Date ) AS Date
 FROM my_table AS r
 GROUP BY r.ID

UNION

SELECT r.ID, max( r.Date )
  FROM 
      my_table AS r
      JOIN ( 
        SELECT ID,
               max( Date ) AS Date
          FROM my_table
         GROUP BY ID) AS maxDat
      ON
      r.ID = maxDat.ID AND
      r.Date != maxDat.Date
 GROUP BY r.ID;

它选择 ID 及其最新日期。 然后,它将这个结果与表格中的类似选择统一起来,其中实际的最新日期被取出,以便您获得第二个最晚日期。如果您需要的不是最近的两个日期,这将变得非常麻烦,但只有两个日期应该没问题,而且可能更快。

【讨论】:

    猜你喜欢
    • 2013-06-14
    • 1970-01-01
    • 2012-06-08
    • 1970-01-01
    • 1970-01-01
    • 2020-02-12
    • 1970-01-01
    • 1970-01-01
    • 2020-03-01
    相关资源
    最近更新 更多