MS-Access:SQL JOIN 和 INSERT INTO 与 WHERE 慢
Posted
技术标签:
【中文标题】MS-Access:SQL JOIN 和 INSERT INTO 与 WHERE 慢【英文标题】:MS-Access : SQL JOIN and INSERT INTO with WHERE slow 【发布时间】:2017-05-08 08:14:13 【问题描述】:长话短说:
通过 INSERT INTO 将具有两个表的 INNER JOIN 的 SELECT 查询插入到新表中。虽然此查询在 20 秒内完成,但在 SELECT 部分添加 WHERE 条件会冻结查询!
详情:
我有两张桌子 (i=1,2)
Table i : Tab_i
ID_i (Long, Indexed, Duplicates possible)
MyDate (Date)
Field_1 (...)
...
Field_N (...)
我创建了一个表 Tab_MATCH 来在比较两个表时存储匹配的 ID
Table Tab_MATCH
ID_1 (Long, Indexed, Duplicates possible)
ID_2 (Long, Indexed, Duplicates possible)
匹配是通过两个表 Tab_1 和 Tab_2 的连接完成的,将匹配的 ID 插入到表 Tab_MATCH 中
INSERT INTO
Tab_MATCH
SELECT
Tab_1.ID_1,
Tab_2.ID_2,
FROM
Tab_1
INNER JOIN
Tab_2
ON
(Tab_1.Field_1 = Tab_2.Field_1) AND
(...) AND
(Tab_1.Field_N = Tab_2.Field_N)
此过程在大约 20 秒内运行良好。 然后我想在 Tab_2 的日期上添加一个约束,例如只考虑 2014 年 3 月 1 日(2014 年 3 月 1 日)之前的条目,所以我添加了
INSERT INTO
Tab_MATCH
SELECT
Tab_1.ID_1,
Tab_2.ID_2,
FROM
Tab_1
INNER JOIN
Tab_2
ON
(Tab_1.Field_1 = Tab_2.Field_1) AND
(...) AND
(Tab_1.Field_N = Tab_2.Field_N)
WHERE
Tab_2.MyDate < #3/1/2014#
此查询现在永远运行。如果我只使用日期约束进行选择,它也会在大约 20 秒内完成,但插入类型会冻结!
我在这里缺少什么?此过程或其他任何连接条目是否涉及任何表扫描? (使用 MS Access 2016(32 位))
【问题讨论】:
MS-Access 的奥秘。很难调试这种东西,因为 Access 没有 EXPLAIN PLAN 机制。您是否尝试过压缩/修复您的数据库? 是的,这很痛苦...我已经压缩/修复(多次)并且还尝试在连接中直接添加 WHERE 子句... INNER JOIN (SELECT * FROM Tab_2 WHERE Tab_2.MyDate < #3/1/2014#) ...
,但没有改进...
我只是尝试通过 VBA 循环在 SELECT 查询上作为 DAO.Recordset 进行插入(是的,我已经在这一点上......)而且在这里它只在计算数字时冻结条目数 Dim rs as DAO.Recordset; set rs = CurrentDb.OpenRecordset("SELECT..."); rs.MoveFirst; rs.MoveLast; Debug.Print rs.RecordCount; rs.Close
rs.MoveLast
命令再次冻结...删除 WHERE 子句也可以正常工作...
制作一个临时表是您的最佳选择。执行不带 WHERE 子句但包含 ID_1
、ID_2
和 mydate
列的 INSERT。然后要么删除所有与日期不匹配的记录,要么使用 WHERE 子句插入另一个表。如果您明白我的意思,否则我会写一个正确的答案
嗯,是的,这可能会有所帮助,但问题总是嵌入在更大的上下文中,对多个表进行多重比较。我将测试这个程序。但总的来说,我想了解这里有和没有 INSERT 的 SELECT 之间的区别,以及 WHERE 子句所扮演的角色,以及为什么它冻结INSERT INTO ... SELECT ... INNERJOIN ... WHERE...
查询,这不是一个非常奇特的而是标准任务...
【参考方案1】:
创建并保存这样的查询:
SELECT *
FROM Tab_2
WHERE MyDate < #3/1/2014#
然后用这个保存的查询替换原始查询中的 Tab_2。
【讨论】:
发布的代码只是一个示例,当然嵌入在更复杂的上下文中。这意味着 WHERE 子句是动态的,需要在不同的条件下应用。我有一个 VBA 脚本在多个表上运行多个比较,工作正常。所以我想使用 ORIGINAL 表(我将受到 *.accdb 文件的 2GB 文件大小限制),而不是为每个比较创建一个 tmp 表。如上面另一条评论所述,我想了解 WHERE 子句对查询的影响... 我刚刚尝试了你的方法,它并没有提高查询速度,即也冻结了。我也看不出外部查询或在我的查询中添加确切代码之间的区别。你能评论一下为什么你会期望有所不同吗? 它强制 Access 在尝试任何连接之前过滤 Tab_2,因此要比较的数据要少得多。真是老套路了。如果冻结了,我猜会发生其他事情;它不能是冻结 Access 的标准。以上是关于MS-Access:SQL JOIN 和 INSERT INTO 与 WHERE 慢的主要内容,如果未能解决你的问题,请参考以下文章
MS-Access 2016 中的“同一张表”LEFT JOIN ON“同一个公共字段”
SQL语句(inner join,left out join,right out join三者的不同