快速选择但慢速插入选择
Posted
技术标签:
【中文标题】快速选择但慢速插入选择【英文标题】:Fast Select but slow Insert Select 【发布时间】:2019-11-24 23:03:05 【问题描述】:我正在尝试
仅当另一个表 final_stock_etablissements(10M 记录)与“警报器”代码匹配时,才从表 final_stock_ul(4M 记录)中获取信息 将结果限制为 1000 在临时表中插入所有内容以下代码非常慢(15 秒):
DROP TABLE IF EXISTS temp_results ;
CREATE TEMPORARY TABLE IF NOT EXISTS temp_results (
siren INT,
denomination VARCHAR(255)
) ENGINE=MYISAM DEFAULT CHARSET=utf8 ;
INSERT INTO temp_results (
siren,
denomination
)
SELECT
ul.siren,
ul.denomination
FROM dw.final_stock_ul ul
WHERE
exists
(
SELECT 1
FROM dw.final_stock_etablissements s
WHERE code_postal = 69001
AND s.siren = ul.siren
)
LIMIT 1000
但是“SELECT”部分本身非常快(0.078 秒):
SELECT
ul.siren,
ul.denomination
FROM dw.final_stock_ul ul
WHERE
exists
(
SELECT 1
FROM dw.final_stock_etablissements s
WHERE code_postal = 69001
AND s.siren = ul.siren
)
LIMIT 1000
INSERT 怎么会比 SELECT 慢这么多?
(只有 1000 条记录要插入)
编辑:在 INSERT 语句中添加了缺失的字段
【问题讨论】:
INSERT
提到一栏; SELECT
提到 2 列。请修复。
final_stock_etablissements 中可以有多个匹配的警报器吗? (我正在考虑使用JOIN
而不是EXISTS
。)
你有INDEX(postal_code, siren)
吗?
@RickJames 是的,它们有很多可能的匹配项(“etablissement”是一个位置,“siren”是一个公司编号,因此它们可以是一个公司的多个位置)-是的,我添加了一个postal_code 和警报器上的复合索引,没有任何结果。仍然无法弄清楚为什么插入会这么慢
【参考方案1】:
我找不到性能缓慢的答案:/
然而,潜在的问题非常普遍,并且在网络上有记录:
仅在匹配另一个表格时列出项目
似乎“IF EXISTS”解决方案或“WHERE IN”解决方案在大型表上运行缓慢
最好的解决方案是使用 JOIN(快得多)。
但是,如果您在第二个表中有多个匹配项,它并不能完全解决问题,因为您将获得多次相同的行结果 (LEFT JOIN only first row)
我找到的解决方案是:
创建要加入的特定表,只有一个可能的匹配用于公共索引和 where 条件 - 在我的例子中,我构建了一个包含两个索引列的表 final_stock_etablissements_derived:警报器和 code_postal(每个警笛 x 邮政编码 1 行) 在索引上进行内部连接(在我的例子中是警报器)并在最后应用 where 条件 两个索引都用了,整体速度很快【讨论】:
【参考方案2】:如果您指望复合索引的性能(在您的 CREATE TABLE 语句中不存在),请尝试使用 InnoDB 作为临时表的引擎,它可能会有所帮助(请参阅 Rick James 的回答:MyISAM vs InnoDB for quick inserts and a composite unique key )...
【讨论】:
以上是关于快速选择但慢速插入选择的主要内容,如果未能解决你的问题,请参考以下文章
直接插入排序 ,折半插入排序 ,简单选择排序, 希尔排序 ,冒泡排序 ,快速排序 ,堆排序 ,归并排序的图示以及代码,十分清楚