为什么 SQLite 不自动将此查询分成两部分?

发布于 2024-11-04 18:31:51 字数 1019 浏览 3 评论 0原文

我有两张桌子要加入。 TABLE_A(包含列 a)和 TABLE_BC(包含列 bc)。 TABLE_BC 上有一个条件。这两个表通过rowid 连接。

SELECT a, b, c 
FROM main.TABLE_A 
INNER JOIN main.TABLE_BC 
WHERE (b > 10.0 AND c < 10.0) 
ON main.TABLE_A.rowid = main.TABLE_BC.rowid 
ORDER BY a;

或者:

SELECT a, b, c 
FROM main.TABLE_A AS s1 
INNER JOIN 
(
  SELECT rowid, b, c 
  FROM main.TABLE_BC 
  WHERE (b > 10.0 AND c < 10.0)
) AS s2 
ON s1.rowid = s2.rowid 
ORDER BY a;

我需要使用不同的 TABLE_As 执行此操作几次,但 TABLE_BC 不会更改。因此,我可以通过为查询的常量部分创建临时内存数据库 (mem) 来加快速度。

CREATE TABLE mem.cache AS 
SELECT rowid, b, c 
FROM main.TABLE_BC 
WHERE (b > 10.0 AND c < 10.0);

接下来(很多)

SELECT a, b, c 
FROM main.TABLE_A 
INNER JOIN mem.cache ON main.TABLE_A.rowid = mem.cache.rowid 
ORDER BY a;

我从上面的所有查询中得到了相同的结果集,但最后一个是迄今为止最快的一个。

我想避免将查询分成两部分。我希望 SQLite 能够自动执行此操作(至少在第二种情况下),但事实并非如此。

为什么?

I have two tables to join. TABLE_A (contains column a) and TABLE_BC (contains columns b and c).
There is a condition on TABLE_BC. The two tables are joined by rowid.

SELECT a, b, c 
FROM main.TABLE_A 
INNER JOIN main.TABLE_BC 
WHERE (b > 10.0 AND c < 10.0) 
ON main.TABLE_A.rowid = main.TABLE_BC.rowid 
ORDER BY a;

Alternatively:

SELECT a, b, c 
FROM main.TABLE_A AS s1 
INNER JOIN 
(
  SELECT rowid, b, c 
  FROM main.TABLE_BC 
  WHERE (b > 10.0 AND c < 10.0)
) AS s2 
ON s1.rowid = s2.rowid 
ORDER BY a;

I need to do this a couple of times with different TABLE_As, but TABLE_BC does not change. I could therefore speed things up by creating a temporary in-memory database (mem) for the constant part of the query.

CREATE TABLE mem.cache AS 
SELECT rowid, b, c 
FROM main.TABLE_BC 
WHERE (b > 10.0 AND c < 10.0);

followed by (many)

SELECT a, b, c 
FROM main.TABLE_A 
INNER JOIN mem.cache ON main.TABLE_A.rowid = mem.cache.rowid 
ORDER BY a;

I get the same result set from all the queries above, but the last is by far the fastest one.

I would like to avoid splitting the query into two parts. I would expect SQLite to do that automatically (at least in the second scenario), but it does not.

Why?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

小糖芽 2024-11-11 18:31:51

SQLite 在优化方面相当轻松。一般经验法则:SmallTable Inner Join BigTable 比相反的要快。

话虽这么说,我想知道您的第一个查询是否会以以下形式运行得更快:

SELECT a, b, c 
FROM main.TABLE_A 
  INNER JOIN main.TABLE_BC ON main.TABLE_A.rowid = main.TABLE_BC.rowid 
WHERE (b > 10.0 AND c < 10.0) 
ORDER BY a;

SQLite is pretty light on optimization. The general rule of thumb: SmallTable Inner Join BigTable is faster than the reverse.

That being said I wonder if your first query would run faster in the following form:

SELECT a, b, c 
FROM main.TABLE_A 
  INNER JOIN main.TABLE_BC ON main.TABLE_A.rowid = main.TABLE_BC.rowid 
WHERE (b > 10.0 AND c < 10.0) 
ORDER BY a;
静待花开 2024-11-11 18:31:51

来自SQLite 用户邮件列表的回答:

简而言之,因为 SQLite 无法读懂你的想法。

要了解答案,请比较执行一个查询的速度(与
一个 TABLE_A) 并创建一个内存数据库,在其中创建一个表
它并在一个查询中使用该表(具有相同的 TABLE_A)。我打赌
第一个选项(无需内存数据库的直接查询)
会快得多。所以 SQLite 选择最快的方式来执行你的
询问。它无法预测未来查询将要理解的内容
如何更快地执行整组查询。你可以这样做并且
您应该将查询分成两部分。

帕维尔

Answer from the SQLite User Mailing List:

In short, because SQLite cannot read your mind.

To understand the answer compare speeds of executing one query (with
one TABLE_A) and creating an in-memory database, creating a table in
it and using that table in one query (with the same TABLE_A). I bet
the first option (straightforward query without in-memory database)
will be much faster. So SQLite selects the fastest way to execute your
query. It cannot predict what the future queries will be to understand
how to execute the whole set of queries faster. You can do that and
you should split your query in two parts.

Pavel

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文