我有一个大规模查询,用于对许多表(每个表有数千行)执行 UNION ALL,然后在返回之前输出到临时表。
旧形式:
LỰA CHỌN *
FROM (SELECT `a` AS `Human readable A`,
`b` AS `Human readable B`,
`c` AS `Human readable C`,
FROM `table1`
LIÊN ĐOÀN TẤT CẢ
LỰA CHỌN
`a` AS `Human readable A`,
`b` AS `Human readable B`,
`c` AS `Human readable C`,
FROM `table2`
LIÊN ĐOÀN TẤT CẢ
LỰA CHỌN
`a` AS `Human readable A`,
`b` AS `Human readable B`,
`c` AS `Human readable C`,
FROM `table3`
) AS temp_table
此查询几乎杀死了数据库(查询需要 20 分钟到 61 分钟之间的任何时间),在此期间 CPU 完全耗尽。
我发现为每个表运行单独的 SELECT 语句最多只需要几秒钟,并决定在应用程序级别将它们合并在一起,该应用程序级别位于不同的物理服务器上,这是一个附加的功能奖金(下面的伪代码)。
$result1 = SELECT
`a` AS `Human readable A`,
`b` AS `Human readable B`,
`c` AS `Human readable C`,
FROM `table1`
$result2 = SELECT
`a` AS `Human readable A`,
`b` AS `Human readable B`,
`c` AS `Human readable C`,
FROM `table2`
$result3 = SELECT
`a` AS `Human readable A`,
`b` AS `Human readable B`,
`c` AS `Human readable C`,
FROM `table3`
$result4 = merge($result1, $result2, $result3)
但是,我觉得这有点不安全,因为查询可能会更新这些单独的选择查询之间的数据。 有没有办法改进我的一组 select 语句查询,使其被视为一个事务(无需写入),以便所有数据都将使用共享读锁锁定并返回。 p>
其他信息
我预测原始表单花费的时间要长得多,因为它花费了大量的 CPU 时间来重新创建/排序组合表中的索引,这是我不需要做的事情(我只需要将结果附加在一起) .
- 所有表都具有完全相同的结构
- 请注意,每个表大约有 34 个
a
AS 人类可读 A
,数据被分成不同的表,因为它们与不同的项目相关。
- 此特定查询中有 20 个联合(21 个表)。
- 使用 InnoDB 表存储数据。我知道这比 MyIsam 对 CPU 的消耗更大,但在了解了 MyIsam 的各种缺点后,我不愿意切换存储引擎。
- 没有 WHERE 子句(数据已通过拆分到表中“预先分组”)
考虑到您的约束,最好的调用是在发出每个连续的 LỰA CHỌN
之前显式锁定表:
SET autocommit=0; -- optional, but this is where and how you must start the transaction if you need one
LOCK TABLES t1 READ, t2 READ, t3 READ;
SELECT a FROM t1;
SELECT a FROM t2;
SELECT a FROM t3;
UNLOCK TABLES; -- beware: implicit COMMIT
除非有某种法律要求将此数据保留在多个表中,否则您确实应该坚持验证将所有这些表合并到一个表中。
Tôi là một lập trình viên xuất sắc, rất giỏi!