标签: join

mySQL 查询优化 — 多重连接或选择 ... where not in (select distinct...)?

背景

我有一个 Drupal 安装访问一个大型用户数据库(~200k 行),我的“人员查找器”功能需要访问所有这些行(以随机顺序)。我似乎无法在 Drupal 的 UI 中使用LIMIT和使用OFFSET(并且我在 Drupal 视图中使用大型数据集进行慢查询时在 Drupal.SE 上有一个与 Drupal 特定的问题略有不同- 更适合在 SQL 或 PHP 中处理?,哪个解决了这个问题,以及这个问题的一部分),但我的特定于 mySQL 的问题如下

我需要根据另一个表中的数据排除一些行(“包括角色 A 中所有不在角色 B、C 或 D 中的用户)。Drupal 生成的查询是有效的

SELECT
    users.uid AS uid,
    /* some columns */,
    RAND() AS random_field
FROM
    users users
    INNER JOIN users_roles users_roles ON users.uid = users_roles.uid
    LEFT JOIN users_roles users_roles2
        ON users.uid = users_roles2.uid
        AND (users_roles2.rid = :views_join_condition_0
          OR users_roles2.rid = :views_join_condition_1 …
Run Code Online (Sandbox Code Playgroud)

mysql performance join subquery query-performance

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

如何使用合并提示隔离 SQL Server 中的复杂查询

我可以理解,如果我加入“单独快速”的单个查询,组合可能会变慢,因为默认执行计划可能不是最佳的。但是,当我知道一个查询的行数非常少时,我想我应该能够使用提示来控制连接。

select cj.a, cv.b
  from (select distinct a from complexJoin) cj -- 2 rows
 inner loop join complexView cv
    on cj.a = cv.a
 order by cj.a, cv.b
Run Code Online (Sandbox Code Playgroud)

如果 cj <1s 和 cv <1s 期望这是 <~2s 但使用任何提示(合并/散列/循环)通常> 1分钟。

我还尝试使用 CROSS APPLY,因为文档声称内部选择对于每个外部行只执行一次。该查询比手动运行两次内部查询需要大约 100 倍的时间,所以也许我不理解文档。

select cj.a, cv.b
  from (select distinct a from complexJoin) cj -- 2 rows
 cross apply (select * from complexView 
               where a = cj.a) cv
 order by cj.a, cv.b
Run Code Online (Sandbox Code Playgroud)

如果我用“cj”的结果填充临时表,然后加入 _with_no_hint_ 或使用交叉应用,它会很快,但我真的必须求助于它吗?如果我使用临时表并尝试“任何”连接提示(循环/合并/散列),它会很慢,所以这可能是一个关键点。

我不相信深入查询计划的深度(两者都是复杂的开始)是解决一般问题所必需的:我只想保证隔离而不诉诸临时表 - 这真的不可能?

join sql-server optimization hints merge

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

查询以比较同一表中的两个数据子集?

我的问题:

我正在尝试与一个表中的数据子集进行比较,并且我有两种方法可以部分工作,并且确定必须有一种更正确的方法来做到这一点。

这里的想法是一个包含关于同一系统随时间推移的数据集的表格,我想比较它们,特别是看看何时有介绍或缺席。请允许我用一个简单的测试表来演示:

mysql> select * from gocore;
+-----+------------+------+----------+----------+
| uid | server     | tag  | software | revision |
+-----+------------+------+----------+----------+
|   1 | enterprise | old  | apache   | 2.2.25   |
|   2 | enterprise | new  | apache   | 2.4.6    |
|   3 | enterprise | new  | tomcat   | 7.0.42   |
|   4 | enterprise | old  | geronimo | 2.1.7    |
+-----+------------+------+----------+----------+
Run Code Online (Sandbox Code Playgroud)

在这个例子中有两个数据集——标签“旧”数据集和标签“新”数据集。每个都反映了在某个时间点采集的数据样本。对于服务器“企业”,我们有一个随时间变化的软件包(apache)、一个引入的软件包(tomcat)和一个消失的软件包(geronimo)。

我的目标:一个可以让我总结“旧”和“新”之间状态的查询:

+------------+----------+----------+----------+
| server     | software | revision | revision |
+------------+----------+----------+----------+ …
Run Code Online (Sandbox Code Playgroud)

mysql join view

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

加入并返回数据时如何从表中删除行?

我有两个疑问:

第一个如下:

SELECT * 
FROM batch bp 
  INNER JOIN sender_log sl ON sl.id=bp.log_id 
    AND bp.protocol='someprotocol'
Run Code Online (Sandbox Code Playgroud)

第二个查询用于删除行:

delete from batch where protocol='someprotocol'
Run Code Online (Sandbox Code Playgroud)

我知道在 postgres 中我们有RETURNING *来返回已删除的行。我想要实现的是删除行并在一个查询中返回它们。我怎样才能做到这一点?

postgresql join delete select

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

如何选择多个 COUNT(*) 列,每个 GROUP BY 都有不同的 WHERE 子句?

我有以下架构:

CREATE TABLE Person (
  PersonId int PRIMARY KEY
)

CREATE TABLE Action (
  ActionId int PRIMARY KEY,
  PersonId int NOT NULL FOREIGN KEY REFERENCES Person(PersonId),
  ActionTime datetime NOT NULL
)
Run Code Online (Sandbox Code Playgroud)

以及以下数据:

INSERT INTO Person (PersonId) VALUES
(1),
(2),
(3),
(4)

INSERT INTO Action (ActionId, PersonId, ActionTime) VALUES
(1, 1, '2014-02-01'),
(2, 1, '2014-02-02'),
(3, 2, '2014-02-02'),
(4, 3, '2014-03-05')
Run Code Online (Sandbox Code Playgroud)

我想运行一个查询,显示每个人在每个月的 15 日之间执行的操作数。例如,我正在尝试以下操作:

SELECT
    Person.PersonId,
    COALESCE(GroupA_Actions_Made, 0) AS GroupA_Actions_Made,
    COALESCE(GroupB_Actions_Made, 0) AS GroupB_Actions_Made
FROM
    Person
    RIGHT OUTER JOIN (
        SELECT …
Run Code Online (Sandbox Code Playgroud)

join sql-server-2008-r2 group-by

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

连接两个表并在单个查询中返回数据和计数

我在 SQL Server 数据库中有两张表,一张有两列,一张有四列:

  1. tbl_email_list

    1. email_list_id int (PK)
    2. email_list_name varchar
  2. tbl_email-details

    1. email_uniq_id int (PK)
    2. email_list_id int (FK)
    3. email_address varchar
    4. blacklist bit

我想在一个应该返回的查询中检索数据

  1. 来自 tbl_email_list 的所有电子邮件列表;
  2. 与特定 email_list_id 关联的 email_address 总数;
  3. 列入白名单的电子邮件地址总数(其中黑名单=0);
  4. 列入黑名单的电子邮件地址总数(其中 blacklist=1)。

join sql-server count

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

仅当有可用行时才应用 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
查看次数