12

我正在尝试将查询结果存储在临时表中以供进一步处理。

create temporary table tmpTest
(
    a FLOAT,
    b FLOAT,
    c FLOAT
)
engine = memory;

insert into tmpTest
(
    select a,b,c from someTable
    where ...
);

但是由于某种原因,插入需要一分钟,而单独的子选择只需要几秒钟。为什么将数据写入临时表而不是将其打印到我的 SQL 管理工具的输出中需要更长的时间???

更新 我的设置:具有 8 个 Debian Linux ndb 数据节点的 MySQL 7.3.2 集群 1 个 SQL 节点(Windows Server 2012)

我正在运行选择的表是 ndb 表。

我试图找出在使用“插入..”时执行计划是否会有所不同,但它们看起来是一样的:(抱歉格式化,stackoverflow 没有表格)

id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY <子查询3> ALL \N \N \N \N \N \N
1 PRIMARY foo ref PRIMARY PRIMARY 3 <subquery3>.fooId 9747434 使用 where
2 SUBQUERY someTable range PRIMARY PRIMARY 3 \N 136933000 使用 where 和 push 条件;使用 MRR;使用临时的;使用文件排序
3 实体化 tmpBar 全部 \N \N \N \N 1000 \N

CREATE TABLE ... SELECT 也很慢。47 秒与 5 秒没有表插入/创建。

4

3 回答 3

4

我在上面写了一条评论,然后偶然发现这是一种解决方法。

这将完成您想做的事情。

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 更好的方法。

将事务隔离级别设置为已提交;插入到表格中 SELECT ... FROM ...

这是一篇相关的文章:

如何改进 INSERT INTO ... SELECT 锁定行为

于 2013-11-01T09:29:53.633 回答
1

我遇到了同样的问题,并且正在玩实际上解决它的子查询。如果选择有大量的行,则插入数据需要很长时间。例子:

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

结合使用 LIMIT 来插入数据不是一个好的选择。因此,您可以使用 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 秒。

于 2016-11-03T09:28:04.757 回答
0

原因与计算机的读写方式以及临时文件的工作方式有关。Select 正在读取硬盘驱动器上的索引文件中的数据,而 insert 正在使用临时文件并正在写入该文件。需要更多的 RAM,这样做更加困难。至于为什么需要一分钟,我不确定,但我认为代码可能有点不正确,所以会有所帮助。

于 2013-10-09T10:36:40.537 回答