SQLite 表别名影响查询性能
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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
如果您在 SQL 语句中多次列出同一个表,并且不提供 JOIN 表的条件,则您将在结果集中创建笛卡尔 JOIN,这将是巨大的:
如果 MyTable 有 1000 条记录,将创建一个包含一百万条记录的结果集。您包含的任何其他选择标准都必须在所有一百万条记录中进行评估。
我不确定这就是你正在做的事情(你的问题很不清楚),但这可能是解决你的问题的开始。
现在更新了答案,发帖者已经添加了正在执行的查询。
您将不得不采取一些技巧才能获得您想要的结果。您需要使用 CASE 和 MAX,不幸的是,CASE 的语法有点冗长:
请在您的实际数据库中尝试一下,看看您会得到什么(当然,您要确保列名已建立索引)。
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:
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:
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).
假设您的表 dbo.Customers 包含一百万行,
不会导致创建该表的副本。
正如 Larry 指出的那样,目前的查询是在表中执行四次笛卡尔积,正如您所观察到的,这会降低您的性能。
更新后的票证指出,希望在一行中包含来自不同查询的 4 个值。这相当简单,假设此语法对 sqllite 有效。
您可以看到以下四个查询在串行运行时生成所需的值,但在 4 行中。
诀窍是简单地将它们作为子查询运行,就像这样有 5 个查询:1 个驱动程序查询,4 个子查询完成所有工作。此模式仅在返回一行时起作用。
Assuming you have table dbo.Customers with a million rows
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.
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.
为表添加别名将导致对 SQL 语句期间存在的原始表的引用。
Aliasing a table will result a reference to the original table that exists for the duration of the SQL statement.