我正在尝试将查询结果存储在临时表中以供进一步处理。
create temporary table tmpTest
(
a FLOAT,
b FLOAT,
c FLOAT
)
engine = memory;
insert into tmpTest
(
select a,b,c from someTable
where ...
);
但由于某种原因,插入需要一分钟,而单独的子选择只需要几秒钟。为什么将数据写入临时表而不是将其打印到我的SQL管理工具的输出需要这么长时间?
更新 我的设置: MySQL 7.3.2集群用 8 Debian Linux ndb数据节点 1 SQL节点(Windows Server 2012)
我正在运行select on的表是一个ndb表。
我试图找出,如果执行计划在使用'insert into ..'时会有所不同,但它们看起来是一样的: (抱歉格式化,stackoverflow没有表格)
id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY <subquery3> ALL \N \N \N \N \N \N 1 PRIMARY foo ref PRIMARY PRIMARY 3 <subquery3>.fooId 9747434 Using where 2 SUBQUERY someTable range PRIMARY PRIMARY 3 \N 136933000 Using where with pushed condition; Using MRR; Using temporary; Using filesort 3 MATERIALIZED tmpBar ALL \N \N \N \N 1000 \N
CREATE TABLE ... SELECT也很慢。 47秒与5秒没有表插入/创建。
答案 0 :(得分:3)
我在上面写了一条评论,然后偶然发现这是一种解决方法。
这将完成你想要做的事。
SELECT * FROM aTable INTO OUTFILE '/tmp/atable.txt';
LOAD DATA INFILE '/tmp/atable.txt' INTO TABLE anotherTable;
请注意,这样做意味着以某种方式管理/ tmp表。如果您尝试将数据选择为已存在的OUTFILE,则会出现错误。因此,您需要生成唯一的临时文件名。然后运行某种类型的cron工作来清理它们。
我猜INFILE和OUTFILE的行为有所不同。如果有人能够对这里发生的事情有所了解来解释mysql的行为,我将不胜感激。
d
这是一种比使用INFILE / OUTFILE更好的方式。
SET TRANSACTION ISOLATION LEVEL READ COMMITTED; 插入表格 SELECT ... FROM ...
以下是相关帖子:
答案 1 :(得分:1)
我遇到了同样的问题,正在玩实际解决它的子查询。 如果select具有大量行,则插入数据需要很长时间。 例如:
INSERT INTO b2b_customers (b2b_name, b2b_address, b2b_language)
SELECT customer_name, customer_address, customer_language
FROM customers
WHERE customer_name LIKE "%john%"
ORDER BY customer_created_date DESC
LIMIT 1
将INSIT与INSERT数据结合使用不是一个好选择。因此,您可以使用2个单独的查询来获取数据和插入,或者您可以使用子查询。 例如:
INSERT INTO b2b_customers (b2b_name, b2b_address, b2b_language)
SELECT * FROM (
SELECT customer_name, customer_address, customer_language
FROM customers
WHERE customer_name LIKE "%john%"
ORDER BY customer_created_date DESC
LIMIT 1
) sub1
这将是一个快速的解决方案,而无需更改您的脚本。
所以我不确定为什么运行子查询需要0.01秒,运行插入需要60秒。我没有限制就获得了1000多个结果。在我的例子中,子查询将性能从60秒提高到0.01秒。
答案 2 :(得分:0)
原因与计算机的读写方式以及临时文件的工作方式有关。 Select正在读取硬盘驱动器上索引文件中的数据,而insert正在使用临时文件并正在写入该文件。需要更多RAM,这样做更加困难。 至于为什么需要一分钟,我不确定,但我认为代码可能有点不正确,所以这会有所贡献。