临时表与内连接中的子查询

时间:2018-01-11 10:02:27

标签: mysql performance subquery temp-tables

两个SQL,返回相同的结果。第一个我的连接在子查询上,第二个最后的查询是一个临时的连接,之前我创建/填充它们

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');

哪些记录会有更好的表现?

3 个答案:

答案 0 :(得分:1)

这两个公式是相同的,只是你的显式临时表版本是3个sql语句而不是1个。也就是说,来回服务器的开销使它变慢。但...

由于隐式临时表位于LEFT JOIN中,因此可以用两种方式之一评估该子查询...

  • 旧版本的MySQL是'转储'并重新评估它。因此很慢。
  • 较新版本会自动创建索引。因此很快。

同时,您可以通过添加合适的索引来加速显式临时表版本。它将是PRIMARY KEY(collegiate_id)。如果INNER JOIN有可能产生重复,请说SELECT DISTINCT

对于“几千”行,您通常不需要担心性能。

Oracle拥有众多选择。 MySQL很少,默认情况下(通常)是最好的。因此,请忽略讨论您可能在MySQL中使用的各种选项的答案。

存在问题
AND  IF(notCollegiate,
        c.collegiate_id NOT IN (notCollegiate),
        '1=1')

我无法分辨哪个表格notCollegiatenotCollegiate不能列出,所以为什么要使用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?

答案 1 :(得分:0)

实际上取决于。您必须测试每个选项的性能。在我的网站上,我有两张桌子,上面有文章和评论。事实证明,为每篇文章调用评论计数比使用单个联合查询更快。 MySQL(像其他数据库一样)缓存查询,因此小的简单查询可以非常快速地运行。

答案 2 :(得分:0)

我没有看到你把这个问题标记为mysql,所以我最初为Oracle解决了问题。以下是我对mySQL的看法。

<强>的MySQL 临时表Memory或Disk有两种选择。对于磁盘,您可以拥有MyIsam - 非事务性和InnoDB事务性。当然,对于非事务性类型的存储,您可以获得更好的性能。

另外,你需要弄清楚你要处理的结果集有多大。对于小结果集,对于大型结果集,内存选项会更快,磁盘选项会更快。

最后,就像我原来的答案一样,你需要弄清楚哪些表现足够好,并选择最具描述性和易读性的选项。

<强>的Oracle

这取决于您正在处理的临时表类型。

您可以拥有基于会话的临时表 - 数据一直保持到注销或基于事务 - 数据一直保持到提交。除此之外,他们可以支持事务日志记录或不支持它。根据配置,您可以从临时表中获得更好的性能。

因为世界上所有表现都是相对热的。最有可能是几千条记录,它们在两个查询之间不会有显着差异。在这种情况下,我会不是为了最容易阅读和理解一个。