SQLite 表别名影响查询性能

发布于 2024-12-04 03:29:53 字数 586 浏览 1 评论 0原文

SQLite 内部如何处理别名?

创建表名别名是否会在内部创建同一个表的副本,还是仅引用同一个表而不创建副本?

当我在代码中创建同一个表的多个别名时,查询的性能会受到严重影响!

就我而言,我有一个表,将其称为 MainTable,其中包含 2 列:名称和值。 我想选择一行中的多个值作为不同的列。例如

名称:a,b,c,d,e,f
值:p、q、r、s、t、u
使得 a 对应于 p 等等。

我想在一行中选择名称 a、b、c 和 d 的值 => p,q,r,s 所以我编写了一个查询,

SELECT t1.name, t2.name, t3.name, t4.name  
FROM MainTable t1, MainTable t2, MainTable t3, MainTable t4
WHERE t1.name = 'a' and t2.name = 'b' and t3.name = 'c' and t4.name = 'd';

当表的大小增加时,编写查询会降低性能,正如拉里在上面正确指出的那样。

有没有有效的方法来检索这个结果。我不擅长 SQL 查询:(

How does SQLite internally treats the alias?

Does creating a table name alias internally creates a copy of the same table or does it just refers to the same table without creating a copy?

When I create multiple aliases of the same table in my code, performance of the query is severely hit!

In my case, I have one table, call it MainTable with namely 2 columns, name and value.
I want to select multiple values in one row as different columns. for example

Name: a,b,c,d,e,f
Value: p,q,r,s,t,u
such that a corresponds to p and so on.

I want to select values for names a,b,c and d in one row => p,q,r,s
So I write a query

SELECT t1.name, t2.name, t3.name, t4.name  
FROM MainTable t1, MainTable t2, MainTable t3, MainTable t4
WHERE t1.name = 'a' and t2.name = 'b' and t3.name = 'c' and t4.name = 'd';

This way f writing the query kills the performance when size of the table increases as rightly pointed above by Larry.

Is there any efficient way to retrieve this result. I am bad at SQL queries :(

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

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

发布评论

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

评论(3

顾北清歌寒 2024-12-11 03:29:53

如果您在 SQL 语句中多次列出同一个表,并且不提供 JOIN 表的条件,则您将在结果集中创建笛卡尔 JOIN,这将是巨大的:

 SELECT * FROM MyTable A, MyTable B;

如果 MyTable 有 1000 条记录,将创建一个包含一百万条记录的结果集。您包含的任何其他选择标准都必须在所有一百万条记录中进行评估。

我不确定这就是你正在做的事情(你的问题很不清楚),但这可能是解决你的问题的开始。

现在更新了答案,发帖者已经添加了正在执行的查询。

您将不得不采取一些技巧才能获得您想要的结果。您需要使用 CASE 和 MAX,不幸的是,CASE 的语法有点冗长:

 SELECT MAX(CASE WHEN name='a' THEN value ELSE NULL END),
        MAX(CASE WHEN name='b' THEN value ELSE NULL END),
        MAX(CASE WHEN name='c' THEN value ELSE NULL END),
        MAX(CASE WHEN name='d' THEN value ELSE NULL END)
  FROM MainTable WHERE name IN ('a','b','c','d');

请在您的实际数据库中尝试一下,看看您会得到什么(当然,您要确保列名已建立索引)。

If you list the same table more than once in your SQL statement and do not supply conditions on which to JOIN the tables, you are creating a cartesian JOIN in your result set and it will be enormous:

 SELECT * FROM MyTable A, MyTable B;

if MyTable has 1000 records, will create a result set with one million records. Any other selection criteria you include will then have to be evaluated across all one million records.

I'm not sure that's what you're doing (your question is very unclear), but it may be a start on solving your problem.

Updated answer now that the poster has added the query that is being executed.

You're going to have to get a little tricky to get the results you want. You need to use CASE and MAX and, unfortunately, the syntax for CASE is a little verbose:

 SELECT MAX(CASE WHEN name='a' THEN value ELSE NULL END),
        MAX(CASE WHEN name='b' THEN value ELSE NULL END),
        MAX(CASE WHEN name='c' THEN value ELSE NULL END),
        MAX(CASE WHEN name='d' THEN value ELSE NULL END)
  FROM MainTable WHERE name IN ('a','b','c','d');

Please give that a try against your actual database and see what you get (of course, you want to make sure the column name is indexed).

小清晰的声音 2024-12-11 03:29:53

假设您的表 dbo.Customers 包含一百万行,

SELECT * from dbo.Customers A

不会导致创建该表的副本。

正如 Larry 指出的那样,目前的查询是在表中执行四次笛卡尔积,正如您所观察到的,这会降低您的性能。

更新后的票证指出,希望在一行中包含来自不同查询的 4 个值。这相当简单,假设此语法对 sqllite 有效。

您可以看到以下四个查询在串行运行时生成所需的值,但在 4 行中。

SELECT t1.name
FROM MainTable t1
WHERE t1.name='a';

SELECT t2.name
FROM MainTable t2
WHERE t2.name='b';

SELECT t3.name
FROM MainTable t3
WHERE t3.name='c';

SELECT t4.name
FROM MainTable t4
WHERE t4.name='d';

诀窍是简单地将它们作为子查询运行,就像这样有 5 个查询:1 个驱动程序查询,4 个子查询完成所有工作。此模式在返回一行时起作用。

SELECT
(
    SELECT t1.name
    FROM MainTable t1
    WHERE t1.name='a'
) AS t1_name
,
(
    SELECT t2.name
    FROM MainTable t2
    WHERE t2.name='b'
) AS t2_name
,
(
    SELECT t3.name
    FROM MainTable t3
    WHERE t3.name='c'
) AS t3_name
, 
(
    SELECT t4.name
    FROM MainTable t4
    WHERE t4.name='d'
) AS t4_name

Assuming you have table dbo.Customers with a million rows

SELECT * from dbo.Customers A

does not result in a copy of the table being created.

As Larry pointed out, the query as it stands is doing a cartesian product across your table four times which, as you has observed, kills your performance.

The updated ticket states the desire is to have 4 values from different queries in a single row. That's fairly simple, assuming this syntax is valid for sqllite

You can see that the following four queries when run in serial produce the desired value but in 4 rows.

SELECT t1.name
FROM MainTable t1
WHERE t1.name='a';

SELECT t2.name
FROM MainTable t2
WHERE t2.name='b';

SELECT t3.name
FROM MainTable t3
WHERE t3.name='c';

SELECT t4.name
FROM MainTable t4
WHERE t4.name='d';

The trick is to simply run them as sub queries like so there are 5 queries: 1 driver query, 4 sub's doing all the work. This pattern will only work if there is one row returned.

SELECT
(
    SELECT t1.name
    FROM MainTable t1
    WHERE t1.name='a'
) AS t1_name
,
(
    SELECT t2.name
    FROM MainTable t2
    WHERE t2.name='b'
) AS t2_name
,
(
    SELECT t3.name
    FROM MainTable t3
    WHERE t3.name='c'
) AS t3_name
, 
(
    SELECT t4.name
    FROM MainTable t4
    WHERE t4.name='d'
) AS t4_name
吲‖鸣 2024-12-11 03:29:53

为表添加别名将导致对 SQL 语句期间存在的原始表的引用。

Aliasing a table will result a reference to the original table that exists for the duration of the SQL statement.

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