Mysql 嵌套多个select语句的性能影响
我正在编写一个查询,它需要在SQL Server和MySQL上运行,需要执行非常长的计算。如果我在一个查询中编写所有代码,那么它将涉及大量的复制和粘贴以及冗余的、难以维护的代码。因此,我编写了一个更紧凑的版本,基本上如下所示: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
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实际上正在创建三个临时表,所以这肯定会增加总的执行时间…如果您看到任何其他值得注意的内容,我会洗耳恭听。这是一个非常有用的信息,让我对开始测试时要查找的内容有了一个很好的了解