当前位置: 首页 > 面试题库 >

性能差异:条件置于INNER JOIN与WHERE子句之间

翟凯
2023-03-14
问题内容

说我有一个表order作为

id | clientid | type | amount | itemid | date
---|----------|------|--------|--------|-----------
23 | 258      | B    | 150    | 14     | 2012-04-03
24 | 258      | S    | 69     | 14     | 2012-04-03
25 | 301      | S    | 10     | 20     | 2012-04-03
26 | 327      | B    | 54     | 156    | 2012-04-04
  • clientid是外键回到client桌子
  • itemid是回到item表的外键
  • type只是BS
  • amount 是一个整数

和一张桌子processed作为

id | orderid | processed | date
---|---------|-----------|---------
41 | 23      | true      | 2012-04-03
42 | 24      | true      | 2012-04-03
43 | 25      | false     | <NULL>
44 | 26      | true      | 2012-04-05

我需要从获取的所有行order,对于同样的clientid在同一个date具有相对type值。请记住type,只能有两个值之一-BS。在上面的示例中,这将是行2324

另一个限制是的相应行processed必须true用于orderid

到目前为止我的查询

SELECT c1.clientid,
       c1.date,
       c1.type,
       c1.itemid,
       c1.amount,
       c2.date,
       c2.type,
       c2.itemid,
       c2.amount

FROM   order c1
INNER JOIN order c2 ON c1.itemid    =  c2.itemid AND
                       c1.date      =  c2.date   AND
                       c1.clientid  =  c2.clientid AND
                       c1.type     <>  c2.type AND
                       c1.id        <  c2.id

INNER JOIN processed p1 ON p1.orderid   =  c1.id AND
                         p1.processed =  true
INNER JOIN processed p2 ON p2.orderid   =  c2.id AND
                         p2.processed =  true

问题:processed = truejoin子句保留为as会减慢查询速度。如果将其移至WHERE子句,则性能会更好。这激起了我的兴趣,
我想知道为什么

主键和相应的外键列被索引,而值列(valueprocessed等等)未被索引。

免责声明:我继承了此数据库结构,性能差异大约为6秒。


问题答案:

您之所以会看到差异,是因为计划者将执行计划放在一起,这显然取决于查询(可以说,应该将两个查询优化为相同,这可能是一个错误)。
)。这意味着计划者认为必须以特定的方式工作才能获得每个语句中的结果。

当您在JOIN中执行此操作时,计划者可能必须从表中进行选择,通过“
True”部分进行过滤,然后加入结果集。我可以想象这是一个大表,因此需要查看大量数据,并且不能高效地使用索引。

我怀疑如果您在WHERE子句中执行此操作,那么计划者将选择一条效率更高的路由(即,基于索引的数据集或预先过滤的数据集)。

您可以通过在两列上添加索引来使联接工作更快(如果不是更快的话)(不确定Postgres是否支持包含的列和多列索引)。

简而言之,计划者面临的问题是正在选择2条不同的路线来获得结果集,其中一条路线的效率不如另一条路线。没有完整的表格信息和EXPLAIN
ANALYZE信息,对于我们来说,原因是不可能的。

如果您想知道为什么特定查询执行此操作的细节,则需要提供更多信息。但是,原因是计划者选择了不同的路线。

其他阅读材料:

http://www.postgresql.org/docs/current/static/explicit-
joins.html

只是略读了一下,似乎postgres规划器并未重新排序联接以对其进行优化。尝试更改语句中的联接顺序,以查看是否获得了相同的性能……只是一个想法。



 类似资料:
  • 问题内容: 我有一个执行查询的SQL Server 2005存储过程。该存储过程采用三个参数。参数如下: @StateID为int, @ CountyID为int, @ CityID为int 这些参数用于查询客户列表。如果参数值不为null,我基本上想做一个“ AND”。但是,我目前无法执行if- else。如果参数值不为null,如何添加这些子句。换一种说法: 问题答案: 加上一些OR语句: 对

  • 问题内容: 我目前有一个查询,它将根据我想使用的任何条件从数据库中提取一堆信息。 如果参数=’‘,我希望能够删除注释部分并仅显示所有行 例如,如果我使用它,它将按该参数搜索,如果我使用它,将按该参数搜索。 我已经尝试使用以下方法和其他一些尝试,但是进展并不很快。 问题答案: 您可能需要考虑构建查询。

  • 问题内容: 在此找到了两个类似的问题,但无法弄清楚如何应用于我的方案。 我的函数有一个名为 @IncludeBelow 的参数。值是0或1(BIT)。 我有这个查询: 如果@IncludeBelow为0,我需要查询如下: 如果@IncludeBelow为1,则最后一行需要排除。(即不应用过滤器)。 我猜想它必须是一条语句,但无法弄清楚语法。 这是我尝试过的: 显然,这是不正确的。 正确的语法是什么

  • 问题内容: 该问题可能特定于SQL Server。当我编写查询时,例如: 是否对表的EACH行执行Case内的Case内的函数调用fnQuarterDate(或任何子查询)? 如果我预先在类似这样的变量中获取函数(或任何子查询)的值,会怎么样呢? 我知道在MySQL中,如果WHERE子句中的IN(..)内有子查询,则对每一行都执行该子查询,我只想为SQL SERVER查找相同的子查询。 … 只需填

  • 问题内容: 例如,我对我的书籍清单有动态过滤器,可以在其中设置特定的颜色,作者和类别。该过滤器可以一次设置多种颜色,也可以设置多种类别。 如何有条件地添加“ where”? 问题答案: 如您在API文档中所见,collection()方法返回一个CollectionReference。CollectionReference扩展了Query。Query.where()和Query.orderBy()

  • 主要内容:所需步骤,示例代码在本教程将演示如何在JDBC应用程序中,从数据库表中查询数据记录, 在查询选择记录时使用WHERE子句添加其他条件。 在执行以下示例之前,请确保您已经准备好以下操作: 具有数据库管理员权限,以在给定模式的数据库表中查询数据记录。 要执行以下示例,需要用实际用户名和密码替换这里用户名()和密码()。 MySQL或数据库已启动并运行。 所需步骤 使用JDBC应用程序查询表中数据记录需要以下步骤: 导入