内部联接中的临时表与子查询
Temp tables vs subqueries in inner join
两者SQL、return结果相同。我的第一个连接在子查询上,第二个最终查询是一个临时连接,之前我 create/populate 他们
SELECT COUNT(*) totalCollegiates, SUM(getFee(c.collegiate_id, dateS)) totalMoney
FROM collegiates c
LEFT JOIN (
SELECT collegiate_id FROM collegiateRemittances r
INNER JOIN remittances r1 USING(remittance_id)
WHERE r1.type_id = 1 AND r1.name = remesa
) hasRemittance ON hasRemittance.collegiate_id = c.collegiate_id
WHERE hasRemittance.collegiate_id IS NULL AND c.typePayment = 1 AND c.active = 1 AND c.exentFee = 0 AND c.approvedBoard = 1 AND IF(notCollegiate, c.collegiate_id NOT IN (notCollegiate), '1=1');
DROP TEMPORARY TABLE IF EXISTS hasRemittance;
CREATE TEMPORARY TABLE hasRemittance
SELECT collegiate_id FROM collegiateRemittances r
INNER JOIN remittances r1 USING(remittance_id)
WHERE r1.type_id = 1 AND r1.name = remesa;
SELECT COUNT(*) totalCollegiates, SUM(getFee(c.collegiate_id, dateS)) totalMoney
FROM collegiates c
LEFT JOIN hasRemittance ON hasRemittance.collegiate_id = c.collegiate_id
WHERE hasRemittance.collegiate_id IS NULL AND c.typePayment = 1 AND c.active = 1 AND c.exentFee = 0 AND c.approvedBoard = 1 AND IF(notCollegiate, c.collegiate_id NOT IN (notCollegiate), '1=1');
对于几千条记录,哪个性能更好?
这要视情况而定。您必须测试每个选项的性能。在我的网站上,我有 2 个表格,其中包含文章和评论。事实证明,为每篇文章调用评论计数 20 次比使用单个联合查询更快。 MySQL(与其他数据库一样)缓存查询,因此小型简单查询可以 运行 惊人地快。
我没有看到您将问题标记为 mysql,所以我最初回答了 Oracle。这是我对 mySQL.
的看法
MySQL
关于临时 tables 内存或磁盘,有两种选择。对于磁盘,您可以拥有 MyIsam - 非事务性和 InnoDB 事务性。当然,对于非事务型存储,您可以期待更好的性能。
此外,您还需要弄清楚您要处理的结果集有多大。对于小结果集,内存选项会更快;对于大结果集,磁盘选项会更快。
最后,正如我最初的回答,您需要弄清楚什么样的性能足够好,然后选择最具描述性和易于阅读的选项。
甲骨文
这取决于您处理的是哪种临时 table。
您可以拥有基于会话的临时 tables - 数据一直保留到注销,或者基于事务 - 数据一直保留到提交。最重要的是,他们可以支持或不支持事务日志记录。根据配置,您可以从临时 table.
获得更好的性能
因为世界上的一切性能都是相对的。很可能对于几千条记录,它不会在两个查询之间产生显着差异。在这种情况下,我不会选择性能最高的,而是选择最容易阅读和理解的。
除了您的显式 temp table 版本是 3 个 sql 语句而不是 1 个之外,这两个公式是相同的。也就是说,来回服务器的开销使其变慢.但是...
由于隐式临时 table 在 LEFT JOIN
中,可以通过以下两种方式之一评估该子查询...
- MySQL 的旧版本是 'dump' 并重新评估了它。因此很慢。
- 较新的版本会自动创建索引。因此快。
同时,您可以通过添加 suitable 索引来加速显式 temp table 版本。它将是 PRIMARY KEY(collegiate_id)
。如果 INNER JOIN
有可能产生重复,那么说 SELECT DISTINCT
.
对于 "a few thousand" 行,您通常不需要担心性能问题。
Oracle 拥有无数的选择。 MySQL 很少,默认值(通常)是最好的。因此,请忽略讨论您 可以 在 MySQL.
中使用的各种选项的答案
有问题
AND IF(notCollegiate,
c.collegiate_id NOT IN (notCollegiate),
'1=1')
我分不清table notCollegiate
在哪个里面。notCollegiate
不能是列表,为什么要用IN
?而是简单地使用 !=
。最后,'1=1'
是一个 3 个字符的字符串;你真的想要那个吗?
性能(任一版本)
remittances
需要 INDEX(type_id, name, remittance_id)
最后 remittance_id
。
collegiateRemittances
需要INDEX(remittance_id)
(除非是PK)。
collegiates
需要 INDEX(typePayment, active, exentFee , approvedBoard)
任意顺序。
底线:比您如何制定查询更担心索引。
哎呀。又一条皱纹。什么是 getFee()
?如果它是存储函数,也许我们需要担心优化它?什么是 dateS?
两者SQL、return结果相同。我的第一个连接在子查询上,第二个最终查询是一个临时连接,之前我 create/populate 他们
SELECT COUNT(*) totalCollegiates, SUM(getFee(c.collegiate_id, dateS)) totalMoney
FROM collegiates c
LEFT JOIN (
SELECT collegiate_id FROM collegiateRemittances r
INNER JOIN remittances r1 USING(remittance_id)
WHERE r1.type_id = 1 AND r1.name = remesa
) hasRemittance ON hasRemittance.collegiate_id = c.collegiate_id
WHERE hasRemittance.collegiate_id IS NULL AND c.typePayment = 1 AND c.active = 1 AND c.exentFee = 0 AND c.approvedBoard = 1 AND IF(notCollegiate, c.collegiate_id NOT IN (notCollegiate), '1=1');
DROP TEMPORARY TABLE IF EXISTS hasRemittance;
CREATE TEMPORARY TABLE hasRemittance
SELECT collegiate_id FROM collegiateRemittances r
INNER JOIN remittances r1 USING(remittance_id)
WHERE r1.type_id = 1 AND r1.name = remesa;
SELECT COUNT(*) totalCollegiates, SUM(getFee(c.collegiate_id, dateS)) totalMoney
FROM collegiates c
LEFT JOIN hasRemittance ON hasRemittance.collegiate_id = c.collegiate_id
WHERE hasRemittance.collegiate_id IS NULL AND c.typePayment = 1 AND c.active = 1 AND c.exentFee = 0 AND c.approvedBoard = 1 AND IF(notCollegiate, c.collegiate_id NOT IN (notCollegiate), '1=1');
对于几千条记录,哪个性能更好?
这要视情况而定。您必须测试每个选项的性能。在我的网站上,我有 2 个表格,其中包含文章和评论。事实证明,为每篇文章调用评论计数 20 次比使用单个联合查询更快。 MySQL(与其他数据库一样)缓存查询,因此小型简单查询可以 运行 惊人地快。
我没有看到您将问题标记为 mysql,所以我最初回答了 Oracle。这是我对 mySQL.
的看法MySQL 关于临时 tables 内存或磁盘,有两种选择。对于磁盘,您可以拥有 MyIsam - 非事务性和 InnoDB 事务性。当然,对于非事务型存储,您可以期待更好的性能。
此外,您还需要弄清楚您要处理的结果集有多大。对于小结果集,内存选项会更快;对于大结果集,磁盘选项会更快。
最后,正如我最初的回答,您需要弄清楚什么样的性能足够好,然后选择最具描述性和易于阅读的选项。
甲骨文
这取决于您处理的是哪种临时 table。
您可以拥有基于会话的临时 tables - 数据一直保留到注销,或者基于事务 - 数据一直保留到提交。最重要的是,他们可以支持或不支持事务日志记录。根据配置,您可以从临时 table.
获得更好的性能因为世界上的一切性能都是相对的。很可能对于几千条记录,它不会在两个查询之间产生显着差异。在这种情况下,我不会选择性能最高的,而是选择最容易阅读和理解的。
除了您的显式 temp table 版本是 3 个 sql 语句而不是 1 个之外,这两个公式是相同的。也就是说,来回服务器的开销使其变慢.但是...
由于隐式临时 table 在 LEFT JOIN
中,可以通过以下两种方式之一评估该子查询...
- MySQL 的旧版本是 'dump' 并重新评估了它。因此很慢。
- 较新的版本会自动创建索引。因此快。
同时,您可以通过添加 suitable 索引来加速显式 temp table 版本。它将是 PRIMARY KEY(collegiate_id)
。如果 INNER JOIN
有可能产生重复,那么说 SELECT DISTINCT
.
对于 "a few thousand" 行,您通常不需要担心性能问题。
Oracle 拥有无数的选择。 MySQL 很少,默认值(通常)是最好的。因此,请忽略讨论您 可以 在 MySQL.
中使用的各种选项的答案 有问题AND IF(notCollegiate,
c.collegiate_id NOT IN (notCollegiate),
'1=1')
我分不清table notCollegiate
在哪个里面。notCollegiate
不能是列表,为什么要用IN
?而是简单地使用 !=
。最后,'1=1'
是一个 3 个字符的字符串;你真的想要那个吗?
性能(任一版本)
remittances
需要INDEX(type_id, name, remittance_id)
最后remittance_id
。collegiateRemittances
需要INDEX(remittance_id)
(除非是PK)。collegiates
需要INDEX(typePayment, active, exentFee , approvedBoard)
任意顺序。
底线:比您如何制定查询更担心索引。
哎呀。又一条皱纹。什么是 getFee()
?如果它是存储函数,也许我们需要担心优化它?什么是 dateS?