标签: join

联接查询中的表顺序

如果我说:

Table1 left join Table2
Run Code Online (Sandbox Code Playgroud)

和说一样吗?:

Table2 right join Table1
Run Code Online (Sandbox Code Playgroud)

换句话说,我是否应该期望从 2 个相同的查询中获得相同的结果,其中唯一改变的是首先写入哪个表以及是使用左连接还是右连接(遵循我上面描述的相同模式?)

join sql-server

7
推荐指数
1
解决办法
386
查看次数

子查询单独运行非常快,但加入时非常慢

ypercube 解决了这个问题。子查询是完全没有必要的,整个事情都可以使用普通连接。不过,MySQL 的优化器无法使用我的原始查询仍然很奇怪。有关问题和许多详细信息,请参见下文。在我的问题底部加上一个完整的解决方案。它基于 ypercube 的答案。

每个子查询都非常快,不到 1 秒。加入了 5-6 个子查询(一些LEFT,一些INNER),时间增加到 400 秒。

我用于测试的整体查询仅返回 441 行。

我尝试将每个子查询放在“CREATE TABLE”查询中。每一个都在不到 1 秒的时间内完成。然后我使用那些新创建的表重新执行外部查询,它的运行时间也远低于 1 秒。所以连接没有实际问题。我id为我创建的表添加了索引。所有表都在匹配id= 上连接id

如何让 MySQL 高效地执行查询?我必须使用临时表吗?我已经编写了一堆 PHP 代码来将多个子查询连接放在一起,所以如果可能的话,我宁愿弄清楚如何使其工作。

我尝试使用“STRAIGHT_JOIN”关键字并删除外部ORDER BY. 这将查询时间减少到 90 秒。但我应该最多获得 1 秒。

我试过STRAIGHT_JOINORDER BY,花了 235 秒。所以看起来外部ORDER BY是一个主要的性能问题。

编辑:

使用临时表进行测试。查询运行速度非常快。但是必须有一种方法可以让 mysql 使用 JOINS 快速完成它。

此外,慢查询日志显示:

Rows_examined: 484006914
Run Code Online (Sandbox Code Playgroud)

4.84 亿行看起来像笛卡尔积。为什么要检查这么多行?

查询具有以下结构:

SELECT t0.`id`, t1.`length`, t2.`height`, t3.`family`
FROM
`products` t0
INNER JOIN
( …
Run Code Online (Sandbox Code Playgroud)

mysql join optimization subquery

7
推荐指数
1
解决办法
2万
查看次数

进行左连接并使每个匹配项都包含一个额外的空行

所以我想做一个左连接,让左表中的每一行都在右表中包含一行空值,即使存在匹配也是如此。

这种类型的连接有名称吗?

有没有比我下面的方法更好的方法(即避免联合)?

SELECT
    T1.C1,
    ...
    T1.CN
    T2.C1,
    ...
    T2.CM
FROM
    Table1 T1
    INNER JOIN Table2 T2
        ON T1.Key1 = T2.Key1

UNION

SELECT
    T1.C1,
    ...
    T1.CN,
    NULL, --NULL 1
    ...
    NULL, --NULL M
FROM
    Table1 T1
Run Code Online (Sandbox Code Playgroud)

(我也可以从左连接开始,然后联合一个选择,就像上面的第二个选择一样,过滤到仅具有匹配 ID 的表,但这仍然是复杂的方法)。

我想知道是否有类似的东西

SELECT
    T1.C1,
    ...
    T1.CN
    T2.C1,
    ...
    T2.CM
FROM
    Table1 T1
    INNER JOIN Table2 T2 INCLUDE_NULL_ROW_WITH_MATCH
        ON T1.Key1 = T2.Key1
Run Code Online (Sandbox Code Playgroud)

如果相关的话,这是专门针对 SQL Server 2008 的。

join sql-server

6
推荐指数
1
解决办法
7056
查看次数

仅当有可用行时才应用 INNER JOIN 否则使用 NULL

+----+-----------+-----------+-------------+----------+
| id | value_id  | parent_id | dropdown_id | name     |
+----+-----------+-----------+-------------+----------+
|  7 | 14945     |  14944    |         57  |4000      |
|  8 | 14944     |  0        |         56  |bbb       |
|  9 | 14943     |  14940    |         59  |comprable |
| 10 | 14942     |  14939    |         59  |comprable |
| 11 | 14940     |  14931    |         58  |3         |
| 12 | 14939     |  14930    |         58  |2         |
| 13 | 14931     |  14929    | …
Run Code Online (Sandbox Code Playgroud)

mysql join

6
推荐指数
2
解决办法
4万
查看次数

按最近的时间加入 2 个表,PostgreSQL 9.6

我有 2 个表:tbl1、tbl2。

CREATE TABLE tbl1(time_1)
AS VALUES
  ( '2017-09-06 15:26:03'::timestamp ),
  ( '2017-09-06 15:26:02' ),
  ( '2017-09-06 15:28:01' ),
  ( '2017-09-06 15:40:00' );

CREATE TABLE tbl2(time_2)
AS VALUES
  ( '2017-09-06 15:29:01'::timestamp ),
  ( '2017-09-06 15:40:00' ),
  ( '2017-09-06 15:23:59' ),
  ( '2017-09-06 15:45:58' );
Run Code Online (Sandbox Code Playgroud)

我想加入表格,因此对于 tbl1 中的每一行都匹配 tbl2 中最接近的时间。输出是:

     time_1                     time_2
---------------------      --------------------
 2017-09-06 15:26:03      2017-09-06 15:23:59      
 2017-09-06 15:26:02      2017-09-06 15:23:59 
 2017-09-06 15:28:01      2017-09-06 15:29:01
 2017-09-06 15:40:00      2017-09-06 15:45:58
Run Code Online (Sandbox Code Playgroud)

我知道如何找到最近时间的单个值:

SELECT * from tbl1 where time_1=INPUT_TIME ORDER BY case …
Run Code Online (Sandbox Code Playgroud)

postgresql join time

6
推荐指数
2
解决办法
5357
查看次数

加入 NULL 键列优化为表和索引扫描

我有一个关于这个查询计划的问题。

我们在测试环境中有一个表 Order_Details_Taxes,它有 11,225,799 行。该表有一个列 OrdTax_PLTax_LoadDtl_Key,它在每一行上都是 NULL。此测试环境的配置方式使此列始终为 NULL。此列上有一个索引。

我使用列的 NULL 值对该表运行了一些查询。NULL INNER JOIN 永远不会产生任何结果。

declare @Keys table (KeyValue decimal(15,0))
insert into @Keys (KeyValue) values (null)

select OrdTax_PLTax_LoadDtl_Key
from @Keys
inner join Order_Details_Taxes
    on OrdTax_PLTax_LoadDtl_Key = KeyValue

select *
from @Keys
inner join Order_Details_Taxes
    on OrdTax_PLTax_LoadDtl_Key = KeyValue
Run Code Online (Sandbox Code Playgroud)

这些是查询计划中的第一个查询。第一个select从亿行表开始并连接到@Keys。第二个select从@Keys 开始,但它对这个表进行聚集索引扫描。

我知道在大多数情况下临时@Tables 是有问题的,所以我将查询更改为使用临时 #Table:

if object_id ('tempdb..#Keys') is not null
    drop table #Keys
create table #Keys (KeyValue decimal(15,0))
insert into #Keys (KeyValue) values (null)

select OrdTax_PLTax_LoadDtl_Key …
Run Code Online (Sandbox Code Playgroud)

null join sql-server execution-plan sql-server-2014

6
推荐指数
1
解决办法
474
查看次数

加入联结表以实现高效排序/分页的推荐方法是什么?

简介: 我有一个简单的数据库模式,但即使只有几十条记录,基本查询的性能也已经成为一个问题。

数据库:PostgreSQL 9.6

简化架构

CREATE TABLE article (
  id bigint PRIMARY KEY,
  title text NOT NULL,
  score int NOT NULL
);
CREATE TABLE tag (
  id bigint PRIMARY KEY,
  name text NOT NULL
);
CREATE TABLE article_tag (
  article_id bigint NOT NULL REFERENCES article (id),
  tag_id bigint NOT NULL REFERENCES tag (id),
  PRIMARY KEY (article_id, tag_id)
);
CREATE INDEX ON article (score);
Run Code Online (Sandbox Code Playgroud)

生产数据信息

所有表都是读/写的。写入量低,每几分钟左右只有一个新记录。

大概记录数:

  • ~66K 篇文章
  • ~63K 标签
  • ~147K article_tags

每篇文章平均 5 个标签。

问题 …

postgresql performance join paging postgresql-performance

6
推荐指数
1
解决办法
3124
查看次数

SQL Server 选择嵌套循环连接维表并对每一行进行查找

我面临 SQL Server 生成非最佳执行计划的问题:嵌套循环连接并寻找维度表并对其执行 2M 读取。

排序操作估计是 100 行而不是 450 K 行,可能会影响计划选择:

NestedLoop:https ://www.brentozar.com/pastetheplan/ ? id = B110MZ2PmNestedLoop 计划

这是在测试数据库中。我们有一个具有相同架构和几乎相同数据的附加数据库。

运行完全相同的查询(均来自 SSMS)使用哈希联接和维度表扫描(32K 读取)生成不同的计划:

HashJoin:https ://www.brentozar.com/pastetheplan/ ? id = r1Jm7b2D7或 哈希计划

我需要帮助来理解和解决问题。

我可以通过提示 Hash Joint 来解决这个问题,但是同一实例上的 2 个相似的 DB 生成不同的计划没有任何意义。

更新 #1:我发现估计的成本是不同的所以当 SQL Server 并行执行时,它会选择一个散列连接。

用单线程会嵌套循环。

更新 #2:在从同一个表中进行 SELECT 时发生了同样的问题。取决于列数(估计成本)。当我减少列数时,执行计划陷入嵌套循环并寻找维度表。

join sql-server execution-plan sql-server-2017

6
推荐指数
1
解决办法
724
查看次数

连接条件与 WHERE...它会产生性能差异吗?

我养成了将连接条件与其他附加条件分开的习惯。不过我理解逻辑执行顺序是:

  1. 在哪里

where如果我在子句中而不是子句中添加附加条件,是否会对性能产生不利影响join?或者这通常是在查询优化阶段得到简化和同等处理的部分?

以下是两个简单的示例查询,它们都返回相同的计划:

USE StackOverflow2010;

-- additional filters in where clause
SELECT TOP 500 p.id
FROM        dbo.Posts p
INNER JOIN  dbo.Votes v ON p.id = v.PostId
WHERE 
    v.VoteTypeId = 2
ORDER BY p.id
;

-- all criteria in on clause
SELECT TOP 500 p.id
FROM        dbo.Posts p
INNER JOIN  dbo.Votes v ON p.id = v.PostId AND   v.VoteTypeId = 2
ORDER BY p.id
;
Run Code Online (Sandbox Code Playgroud)

我想补充一点,如果我编写较长的分析语句,通常跨越 100 行以上(格式化),我会尝试尽快减少结果集,通常使用派生表,并在到达连接之前添加一个额外的位置。

performance join sql-server

6
推荐指数
2
解决办法
1万
查看次数

可以使用 CASE 选择要 JOIN 的表吗?

我正在尝试使用 CASE 表达式来选择每行应与哪个表连接。

假设我的游戏中有一个 item_instances 表,其中包含游戏世界中的所有项目,其中一些项目是 item_templates 表中通用项目的千篇一律的副本,而其他项目则以模板开始,然后当玩家使用它们时获得独特的属性。它们现在存储在 unique_items 表中。

因此,当我在 item_instances 表中找到某个项目的记录时,我想查找有关它的更多信息,并且需要从正确的表中提取该信息。

这是我一直在尝试但没有成功的事情:

SELECT item_table, item_id, *
FROM item_instances AS ii
JOIN
CASE ii.item_table
    WHEN 0 THEN 'item_templates'
    WHEN 1 THEN 'unique_items'
    ELSE 'unique_items'
END
ON CASE = ii.item_id;
Run Code Online (Sandbox Code Playgroud)

如果有语法的快速修复,我很想听听。或者,如果这是您在概念上无法做到的事情 - 让每一行选择自己的连接 - 我很乐意获得更深入解释的链接。

过去,我通过执行两个 SELECT 来完成类似的操作,其中一个针对 item_templates 表,另一个针对 unique_items 表,并采用它们的 UNION。这感觉是一种更正确且更少浪费的方法。如果不是出于某种原因与 SQL 更深层次的架构有关,我想了解为什么。

postgresql join case

6
推荐指数
1
解决办法
9300
查看次数