Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/performance/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
非常基本的通用sql(效率)原则_Sql_Performance_Select_Join - Fatal编程技术网

非常基本的通用sql(效率)原则

非常基本的通用sql(效率)原则,sql,performance,select,join,Sql,Performance,Select,Join,这两条SQL语句中的哪一条在大多数情况下花费的时间更少? (一) (二) 还是它们是一样的? 看起来(2)会更快 两者都不如此查询有效: SELECT table_a.foo, table_b.zoo FROM table_a JOIN table_b ON table_a.id = table_b.id AND table_b.bar = 'something' 请注意tableb上的额外条件是如何在连接条件中,而不是where子句中,这意味着在进行连接时对其进行计算,这样可

这两条SQL语句中的哪一条在大多数情况下花费的时间更少?
(一)

(二)

还是它们是一样的?

看起来(2)会更快

两者都不如此查询有效:

SELECT
    table_a.foo,
    table_b.zoo
FROM table_a
JOIN table_b
ON table_a.id = table_b.id
AND table_b.bar = 'something'
请注意tableb上的额外条件是如何在连接条件中,而不是where子句中,这意味着在进行连接时对其进行计算,这样可以避免向临时结果集中添加大量行


如果它位于where子句中,则将在进行所有联接后对其进行计算,因为where子句是结果集上的筛选器。

两者都不如此查询有效:

SELECT
    table_a.foo,
    table_b.zoo
FROM table_a
JOIN table_b
ON table_a.id = table_b.id
AND table_b.bar = 'something'
请注意tableb上的额外条件是如何在连接条件中,而不是where子句中,这意味着在进行连接时对其进行计算,这样可以避免向临时结果集中添加大量行


如果它在where子句中,它将在所有联接完成后进行计算,因为where子句是结果集上的一个过滤器。

根据我的理解,查询1将花费更少的时间,因为在第二次查询中

SELECT *
        FROM   table_b
        WHERE  bar = 'something'

将首先运行,然后它将与外部查询进行交叉检查。

根据我的理解,查询1将花费更少的时间,因为在第二个查询中

SELECT *
        FROM   table_b
        WHERE  bar = 'something'

将首先运行,然后它将与外部查询进行交叉检查。

其他答案和注释是猜测或概括

真正的答案是,这取决于几个方面,包括:

  • SQL优化器的实现;您正在使用哪个品牌的RDBMS?MySQL?Microsoft SQL Server?神谕你应该用合适的品牌来标记你的问题

  • 表定义,包括相关索引

  • 表的大小,以及与条件匹配的表子集的大小

  • 相对于缓存大小的数据大小

  • 等等

诚然,正如@Colin'tHart在评论中提到的,SQL应该是一种抽象的声明性语言。因此,您应该能够声明两个不同的查询,它们将产生相同的结果,RDBMS应该将其转换为收集数据的最佳方式。理论上很好,但实际上,magic的好坏取决于软件设计者实现代码的案例数量

因此,您在本问题标题中提到的最基本的通用sql(效率)原则应该是:

衡量绩效——不要猜测或概括。

为了进一步研究这一点,您应该从SQL优化器获得一份报告,说明它打算如何访问表和索引以实现查询。大多数RDBMS产品都有一个名为EXPLAIN的语句变体,它允许您为给定的查询获取此报告。如果RDBMS成功地抽象了这个案例,那么对于您显示的两个示例查询,解释报告应该是相同的

例如,我对一个测试MySQL数据库进行了类似的查询。解释显示,运行派生表子查询需要额外的步骤,然后使用该子查询查找匹配的行

mysql> EXPLAIN SELECT c.*, t.* FROM cast_info c 
JOIN ( SELECT * FROM title WHERE title = 'Star Wars') t ON c.movie_id = t.id\G

*************************** 1. row ***************************
           id: 1
  select_type: PRIMARY
        table: <derived2>
         type: ALL
possible_keys: NULL
          key: NULL
      key_len: NULL
          ref: NULL
         rows: 8
        Extra: NULL
*************************** 2. row ***************************
           id: 1
  select_type: PRIMARY
        table: c
         type: ref
possible_keys: movie_id
          key: movie_id
      key_len: 4
          ref: t.id
         rows: 9
        Extra: NULL
*************************** 3. row ***************************
           id: 2
  select_type: DERIVED
        table: title
         type: ref
possible_keys: title
          key: title
      key_len: 152
          ref: const
         rows: 8
        Extra: Using where
使用SQL-89(逗号样式)连接语法的处理方式与使用
join
语法的查询相同:

mysql> EXPLAIN SELECT c.*, t.* FROM cast_info c, title t 
WHERE c.movie_id = t.id AND title = 'Star Wars'\G

*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: t
         type: ref
possible_keys: PRIMARY,title
          key: title
      key_len: 152
          ref: const
         rows: 8
        Extra: Using where
*************************** 2. row ***************************
           id: 1
  select_type: SIMPLE
        table: c
         type: ref
possible_keys: movie_id
          key: movie_id
      key_len: 4
          ref: imdb.t.id
         rows: 9
        Extra: NULL
这只是MySQL的结果。另一个RDBMS的优化器可能会有不同的行为,其EXPLAIN的输出肯定会有所不同。关键是,您有可用的工具,可以自己测试查询的优化计划


解释报告就是这样一种工具。但是EXPLAIN通常只显示优化器计划做什么,而不实际运行查询。您还可以使用探查器工具来运行查询并获得更精确的执行时间度量。可用的探查器工具取决于您的RDBMS品牌。

其他答案和评论是猜测或概括

真正的答案是,这取决于几个方面,包括:

  • SQL优化器的实现;您正在使用哪个品牌的RDBMS?MySQL?Microsoft SQL Server?神谕你应该用合适的品牌来标记你的问题

  • 表定义,包括相关索引

  • 表的大小,以及与条件匹配的表子集的大小

  • 相对于缓存大小的数据大小

  • 等等

诚然,正如@Colin'tHart在评论中提到的,SQL应该是一种抽象的声明性语言。因此,您应该能够声明两个不同的查询,它们将产生相同的结果,RDBMS应该将其转换为收集数据的最佳方式。理论上很好,但实际上,magic的好坏取决于软件设计者实现代码的案例数量

因此,您在本问题标题中提到的最基本的通用sql(效率)原则应该是:

衡量绩效——不要猜测或概括。

为了进一步研究这一点,您应该从SQL优化器获得一份报告,说明它打算如何访问表和索引以实现查询。大多数RDBMS产品都有一个名为EXPLAIN的语句变体,它允许您为给定的查询获取此报告。如果RDBMS成功地抽象了这个案例,那么对于您显示的两个示例查询,解释报告应该是相同的

例如,我对一个测试MySQL数据库进行了类似的查询。解释显示,运行派生表子查询需要额外的步骤,然后使用该子查询查找匹配的行

mysql> EXPLAIN SELECT c.*, t.* FROM cast_info c 
JOIN ( SELECT * FROM title WHERE title = 'Star Wars') t ON c.movie_id = t.id\G

*************************** 1. row ***************************
           id: 1
  select_type: PRIMARY
        table: <derived2>
         type: ALL
possible_keys: NULL
          key: NULL
      key_len: NULL
          ref: NULL
         rows: 8
        Extra: NULL
*************************** 2. row ***************************
           id: 1
  select_type: PRIMARY
        table: c
         type: ref
possible_keys: movie_id
          key: movie_id
      key_len: 4
          ref: t.id
         rows: 9
        Extra: NULL
*************************** 3. row ***************************
           id: 2
  select_type: DERIVED
        table: title
         type: ref
possible_keys: title
          key: title
      key_len: 152
          ref: const
         rows: 8
        Extra: Using where
使用SQL-89(逗号样式)连接语法的处理方式与使用
join
语法的查询相同:

mysql> EXPLAIN SELECT c.*, t.* FROM cast_info c, title t 
WHERE c.movie_id = t.id AND title = 'Star Wars'\G

*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: t
         type: ref
possible_keys: PRIMARY,title
          key: title
      key_len: 152
          ref: const
         rows: 8
        Extra: Using where
*************************** 2. row ***************************
           id: 1
  select_type: SIMPLE
        table: c
         type: ref
possible_keys: movie_id
          key: movie_id
      key_len: 4
          ref: imdb.t.id
         rows: 9
        Extra: NULL
这只是MySQL的结果。另一个RDBMS的优化器可能会有不同的行为,其EXPLAIN的输出肯定会有所不同。重点是t