Mysql 嵌套多个select语句的性能影响

Mysql 嵌套多个select语句的性能影响,mysql,sql,sql-server,tsql,Mysql,Sql,Sql Server,Tsql,我正在编写一个查询,它需要在SQL Server和MySQL上运行,需要执行非常长的计算。如果我在一个查询中编写所有代码,那么它将涉及大量的复制和粘贴以及冗余的、难以维护的代码。因此,我编写了一个更紧凑的版本,基本上如下所示: SELECT calc3... FROM ( SELECT calc2... FROM ( SELECT calc1... FROM original_table ) ) pid Name 1 Value1 1

我正在编写一个查询,它需要在SQL Server和MySQL上运行,需要执行非常长的计算。如果我在一个查询中编写所有代码,那么它将涉及大量的复制和粘贴以及冗余的、难以维护的代码。因此,我编写了一个更紧凑的版本,基本上如下所示:

SELECT calc3...
FROM 
(
  SELECT calc2...
  FROM
  (
    SELECT calc1...
    FROM original_table
  )
)
pid     Name
1       Value1
1       Value2
1       Value4
2       Value2
2       Value5
3
4       Value1
4       Value1
4       Value4
pid     Output
1       'Many values'
2       'Two and five'
3       'Missing'
4       'Values 1 and 4'
SELECT pid,
CASE
    WHEN TotalValues > 3 THEN 'Many values'
    WHEN TotalValues = 2 AND Value2 = 5 AND Value5 = 1 THEN 'Two and five'
    WHEN TotalValues = 2 AND Value1 = 1 AND Value4 = 1 THEN 'Values 1 and 4'
    WHEN TotalValues = 1 AND Value1 = 1 THEN 'Only value 1'
    When TotalValues = 0 THEN 'Missing' 
    -- About a dozen more of these combinations
END as OutputValue
FROM
(
    SELECT *, Value1 + Value7 as TotalValues
    FROM
    (
        SELECT distinct p.pId
        COALESCE(MAX(CASE WHEN rc.Name = 'Value1' THEN 1 ELSE 0 END),0) as Value1,
        -- more of these that I'm omitting for concision
        COALESCE(MAX(CASE WHEN rc.Name = 'Value7' THEN 1 ELSE 0 END),0) as Value7,
        FROM primary_table AS p 
        LEFT JOIN rc on rc.code=p.code
        WHERE p.desiredRecords = TRUE
        GROUP BY p.pid
    ) t1
) t2
有没有理由相信这会导致业绩不佳?e、 g.每个选择是否会导致SQL Server或MySQL在后台创建额外的临时表,从而使执行时间增加三倍

计算不涉及查询任何其他表,只需将列值相加,将整数映射到字符串等

我只能访问一个小的测试数据集,所以我无法运行它并计时,因为使用小数据集运行不到一秒钟。我没有查看执行计划的权限。因此,我不确定如何验证这不会是一场灾难,从性能角度来看。(我可以在生产数据库的副本上进行测试,但这是一个漫长而痛苦的过程)

编辑:为了清楚起见,我将在生产数据库的副本上进行测试,我只是希望在这样做之前看看这里是否有任何明显的缺陷,因为这样做将是一个时间密集的过程。e、 如果我多次调用ALTERTABLE,可能有人会指出,对于MySQL来说,ALTERTABLE可能会非常慢,所以最好将所有调用合并到一个调用中,或者完全避免调用

编辑2:

该表如下所示:

SELECT calc3...
FROM 
(
  SELECT calc2...
  FROM
  (
    SELECT calc1...
    FROM original_table
  )
)
pid     Name
1       Value1
1       Value2
1       Value4
2       Value2
2       Value5
3
4       Value1
4       Value1
4       Value4
pid     Output
1       'Many values'
2       'Two and five'
3       'Missing'
4       'Values 1 and 4'
SELECT pid,
CASE
    WHEN TotalValues > 3 THEN 'Many values'
    WHEN TotalValues = 2 AND Value2 = 5 AND Value5 = 1 THEN 'Two and five'
    WHEN TotalValues = 2 AND Value1 = 1 AND Value4 = 1 THEN 'Values 1 and 4'
    WHEN TotalValues = 1 AND Value1 = 1 THEN 'Only value 1'
    When TotalValues = 0 THEN 'Missing' 
    -- About a dozen more of these combinations
END as OutputValue
FROM
(
    SELECT *, Value1 + Value7 as TotalValues
    FROM
    (
        SELECT distinct p.pId
        COALESCE(MAX(CASE WHEN rc.Name = 'Value1' THEN 1 ELSE 0 END),0) as Value1,
        -- more of these that I'm omitting for concision
        COALESCE(MAX(CASE WHEN rc.Name = 'Value7' THEN 1 ELSE 0 END),0) as Value7,
        FROM primary_table AS p 
        LEFT JOIN rc on rc.code=p.code
        WHERE p.desiredRecords = TRUE
        GROUP BY p.pid
    ) t1
) t2
需要将其转换为如下表:

SELECT calc3...
FROM 
(
  SELECT calc2...
  FROM
  (
    SELECT calc1...
    FROM original_table
  )
)
pid     Name
1       Value1
1       Value2
1       Value4
2       Value2
2       Value5
3
4       Value1
4       Value1
4       Value4
pid     Output
1       'Many values'
2       'Two and five'
3       'Missing'
4       'Values 1 and 4'
SELECT pid,
CASE
    WHEN TotalValues > 3 THEN 'Many values'
    WHEN TotalValues = 2 AND Value2 = 5 AND Value5 = 1 THEN 'Two and five'
    WHEN TotalValues = 2 AND Value1 = 1 AND Value4 = 1 THEN 'Values 1 and 4'
    WHEN TotalValues = 1 AND Value1 = 1 THEN 'Only value 1'
    When TotalValues = 0 THEN 'Missing' 
    -- About a dozen more of these combinations
END as OutputValue
FROM
(
    SELECT *, Value1 + Value7 as TotalValues
    FROM
    (
        SELECT distinct p.pId
        COALESCE(MAX(CASE WHEN rc.Name = 'Value1' THEN 1 ELSE 0 END),0) as Value1,
        -- more of these that I'm omitting for concision
        COALESCE(MAX(CASE WHEN rc.Name = 'Value7' THEN 1 ELSE 0 END),0) as Value7,
        FROM primary_table AS p 
        LEFT JOIN rc on rc.code=p.code
        WHERE p.desiredRecords = TRUE
        GROUP BY p.pid
    ) t1
) t2
其中,输出列中的值基于给定pid在第一个表的名称列中的值。不幸的是,不可能通过连接名称值或类似的东西来派生这些值,它们非常特殊,需要单独定义

我的代码经过一些简化,如下所示:

SELECT calc3...
FROM 
(
  SELECT calc2...
  FROM
  (
    SELECT calc1...
    FROM original_table
  )
)
pid     Name
1       Value1
1       Value2
1       Value4
2       Value2
2       Value5
3
4       Value1
4       Value1
4       Value4
pid     Output
1       'Many values'
2       'Two and five'
3       'Missing'
4       'Values 1 and 4'
SELECT pid,
CASE
    WHEN TotalValues > 3 THEN 'Many values'
    WHEN TotalValues = 2 AND Value2 = 5 AND Value5 = 1 THEN 'Two and five'
    WHEN TotalValues = 2 AND Value1 = 1 AND Value4 = 1 THEN 'Values 1 and 4'
    WHEN TotalValues = 1 AND Value1 = 1 THEN 'Only value 1'
    When TotalValues = 0 THEN 'Missing' 
    -- About a dozen more of these combinations
END as OutputValue
FROM
(
    SELECT *, Value1 + Value7 as TotalValues
    FROM
    (
        SELECT distinct p.pId
        COALESCE(MAX(CASE WHEN rc.Name = 'Value1' THEN 1 ELSE 0 END),0) as Value1,
        -- more of these that I'm omitting for concision
        COALESCE(MAX(CASE WHEN rc.Name = 'Value7' THEN 1 ELSE 0 END),0) as Value7,
        FROM primary_table AS p 
        LEFT JOIN rc on rc.code=p.code
        WHERE p.desiredRecords = TRUE
        GROUP BY p.pid
    ) t1
) t2
编辑3:

在SQLYG中运行MySQL查询探查器的结果

我只能访问一个小的测试数据集,所以我无法运行它并 计时它,因为它只需要不到一秒钟的时间就可以运行小的 数据集。我没有查看执行计划的权限。所以 我不知道如何验证这不会是一场灾难, 性能方面。(我可以在生产文件的副本上进行测试 数据库,但这是一个漫长而痛苦的过程)


这就是你需要解决的问题。陌生人对多个数据库引擎上的假想查询的性能的猜测是不可能的。

MySQL倾向于具体化子查询。对于较新的版本,它并不总是这样做。但是由于这个原因,一般倾向于避免不必要的子查询

SQL Server和其他数据库的优化技术要复杂得多。我不知道SQL Server中有什么东西会刺激子查询的具体化。如果查看复杂SQL查询的执行计划,您将很难确定子查询的位置。所以,在大多数数据库中,我不会担心它


CTE是另一回事——你不用问它们,但它们是自然的后续产品。有些数据库从未实现CTE。我认为有些总是实现CTE。有些人有时会将它们具体化。为此,您需要对所使用的数据库和版本保持敏感。

如果没有进一步的信息,就无法向您提供建议。您所使用的模式在一种情况下是完全可以接受的,而在另一种情况下是不可以接受的。这样,我们至少可以验证您没有从任何表中使用SELECT*,有用于减少所选数据的WHERE,JOIN在=的每一侧都有索引,以及许多其他详细信息。@WilsonHauck遗憾的是,我没有能力调用EXPLAIN。不过,如果您想看一看,我确实添加了一个带有简化版代码的编辑。在任何情况下,我认为我的代码都不应该遇到您提到的任何问题。您可以访问MySQL命令提示符并选择NOW()@WilsonHauck啊哈,刚刚想起我可以让其他人在MySQL中运行我的解释。我已经添加了一个结果的图像-看起来MySQL实际上正在创建三个临时表,所以这肯定会增加总的执行时间…如果您看到任何其他值得注意的内容,我会洗耳恭听。这是一个非常有用的信息,让我对开始测试时要查找的内容有了一个很好的了解