过滤MySQL中的行效率

时间:2015-12-10 23:48:52

标签: mysql sql-server join filter operator-precedence

我正在学习来自科学编程背景的SQL(Matlab,Python)。操作顺序极大地决定了这些语言的计算效率,我想知道SQL是否相同。我想在学习SQL的同时尽早开发出良好的编程策略,而不是在以后对它们进行改进。我的问题涉及效率。

方案: 我正在尝试使用另一个表(job_log_test)中的列的信息从一个表(report_data)中过滤掉行。这两个表具有相同的索引对应关系,每行与单个作业相关。我已经找到了两个 - 可能是非最优的 - 解决这个问题的方法:

解决方案1:首先将两个表中相关列的所有行连接在一起,然后根据源自bill_customer表的report_data列中的值过滤行

SELECT xxx.job_number, xxx.customer_name 
FROM (
  SELECT job_number, customer_name, bill_customer 
      FROM job_log_test 
      INNER JOIN report_data 
      ON job_log_test.job_log_test_id = report_data.report_data_id
    )xxx 
WHERE bill_customer IS TRUE;

解决方案2:report_data,运行子查询以生成要提取的行的索引列表。然后,使用列表从job_log_test中提取所需的行。

SELECT job_number, customer_name 
FROM job_log_test 
WHERE job_log_test_id 
IN (
  SELECT report_data_id 
    FROM report_data 
    WHERE bill_customer IS TRUE
);

有经验的SQL程序员推荐哪些解决方案(如果有的话)?

非常感谢你的时间!

1 个答案:

答案 0 :(得分:2)

早在RDBMSes实现相当简单的早期阶段,您实际上可以通过这种方式手动优化事物。使用IN(的查询可能会更糟糕。

如今,你仍然可以优化这样的东西,但仅在极少数情况下,因为RDBMS已经变得非常复杂,它们包含Query Optimizers (wikipedia),它分析你的查询并以更优化的形式重述它,甚至考虑到你正在引用的各个表中的行数等事项。

因此,您最好的选择是以最简单直接的形式陈述您的查询:

  SELECT job_number, customer_name, bill_customer 
      FROM job_log_test 
      INNER JOIN report_data 
      ON job_log_test.job_log_test_id = report_data.report_data_id
      WHERE bill_customer IS TRUE;

让查询优化器担心其余部分。

此外,查询优化器的存在意味着您永远无法确定尝试手动优化查询是否会产生更好或更差的结果。

当然,在某些情况下,您的手动优化查询可能比查询优化器可能提出的更好。在其他情况下,您的手动优化查询可能会以阻止查询优化器改进它的方式进行说明,因此您可能会比使用最简单的表单获得更差的性能。最后,您的手动优化查询可能会使查询优化器更加混乱,从而产生更差的性能。

因此,如果您认为可以手动优化查询,请继续尝试,但始终比较手动优化查询与未优化查询的性能,您将在大多数情况下看到(授予,并非所有情况都没有结果。