MySQL 中的过滤行效率
Filtering rows efficiency in MySQL
我正在学习 SQL 来自科学编程背景(Matlab,Python)。操作顺序极大地决定了这些语言的计算效率,我想知道 SQL 是否相同。我想尽早制定良好的编程策略,同时学习 SQL,而不是以后再改进它们。我的问题是关于效率。
场景:
我正在尝试使用来自另一个 table (report_data
) 中的列的信息从一个 table (job_log_test
) 中过滤掉行。两个 table 具有相同的索引对应关系,每一行都属于一个单独的作业。我已经找到了两个——可能不是最佳的——解决这个问题的方法:
解决方案 1: 首先将来自两个 table 的相关列的所有行连接在一起,然后根据 bill_customer
列中的值过滤行源自 report_data
table.
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 程序员推荐以下哪些解决方案(如果有的话)?
非常感谢您的宝贵时间!
在 RDBMS 的实现相当简单的早期,您实际上可以一直以这种方式手动优化事物。 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;
剩下的让查询优化器操心。
此外,查询优化器的存在意味着您永远无法确定手动优化查询的尝试是否会产生更好或更差的结果。
当然,在某些情况下,您的手动优化查询可能比查询优化器可能提出的更好。在其他情况下,您的手动优化查询可能会以阻止查询优化器对其进行改进的方式进行陈述,因此与使用最简单的形式相比,您的性能可能会更差。最后,您的手动优化查询可能会使查询优化器更加混乱,从而产生更差的性能。
因此,如果您认为可以手动优化查询,请继续尝试,但始终将手动优化查询的性能与未优化查询的性能进行比较,您会发现在大多数 ( granted, not all) cases it is fruitless.
我正在学习 SQL 来自科学编程背景(Matlab,Python)。操作顺序极大地决定了这些语言的计算效率,我想知道 SQL 是否相同。我想尽早制定良好的编程策略,同时学习 SQL,而不是以后再改进它们。我的问题是关于效率。
场景:
我正在尝试使用来自另一个 table (report_data
) 中的列的信息从一个 table (job_log_test
) 中过滤掉行。两个 table 具有相同的索引对应关系,每一行都属于一个单独的作业。我已经找到了两个——可能不是最佳的——解决这个问题的方法:
解决方案 1: 首先将来自两个 table 的相关列的所有行连接在一起,然后根据 bill_customer
列中的值过滤行源自 report_data
table.
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 程序员推荐以下哪些解决方案(如果有的话)?
非常感谢您的宝贵时间!
在 RDBMS 的实现相当简单的早期,您实际上可以一直以这种方式手动优化事物。 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;
剩下的让查询优化器操心。
此外,查询优化器的存在意味着您永远无法确定手动优化查询的尝试是否会产生更好或更差的结果。
当然,在某些情况下,您的手动优化查询可能比查询优化器可能提出的更好。在其他情况下,您的手动优化查询可能会以阻止查询优化器对其进行改进的方式进行陈述,因此与使用最简单的形式相比,您的性能可能会更差。最后,您的手动优化查询可能会使查询优化器更加混乱,从而产生更差的性能。
因此,如果您认为可以手动优化查询,请继续尝试,但始终将手动优化查询的性能与未优化查询的性能进行比较,您会发现在大多数 ( granted, not all) cases it is fruitless.