解决 MySQL“无法重新打开表”问题 错误
我目前正忙于实现一个过滤器,我需要为每个要过滤的“标签”生成一个 INNER JOIN 子句。
问题是,在执行完一大堆 SQL 之后,我有一个表,其中包含进行选择所需的所有信息,但对于每个生成的 INNER JOIN 我再次需要它,
这基本上看起来像:
SELECT
*
FROM search
INNER JOIN search f1 ON f1.baseID = search.baseID AND f1.condition = condition1
INNER JOIN search f2 ON f2.baseID = search.baseID AND f2.condition = condition2
...
INNER JOIN search fN ON fN.baseID = search.baseID AND fN.condition = conditionN
这可行,但我更喜欢“搜索”表是临时的(如果它不是普通表,它可能会小几个数量级),但这给了我一个非常烦人的错误:无法重新打开表
一些研究引导我到这个错误报告,但 MySQL 的人们似乎并不关心这一点这样的基本功能(多次使用表)不适用于临时表。 我在这个问题上遇到了很多可扩展性问题。
是否有任何可行的解决方法,不需要我管理潜在的大量临时但非常真实的表,或者让我维护一个包含所有数据的巨大表?
亲切的问候,Kris
[附加]
GROUP_CONCAT 答案在我的情况下不起作用,因为我的条件是按特定顺序排列的多个列,它会使我需要的 AND 变成 OR。 然而,它确实帮助我解决了之前的问题,所以现在不再需要该表,无论是否是临时表。 我们只是想得太笼统,无法解决我们的问题。 过滤器的整个应用现在已从大约一分钟缩短到远低于四分之一秒。
I'm currently busy implementing a filter of sorts for which I need to generate an INNER JOIN clausse for every "tag" to filter on.
The problem is that after a whole bunch of SQL, I have a table that contains all the information I need to make my selection, but I need it again for every generated INNER JOIN
This basically looks like:
SELECT
*
FROM search
INNER JOIN search f1 ON f1.baseID = search.baseID AND f1.condition = condition1
INNER JOIN search f2 ON f2.baseID = search.baseID AND f2.condition = condition2
...
INNER JOIN search fN ON fN.baseID = search.baseID AND fN.condition = conditionN
This works but I would much prefer the "search" table to be temporary (it can be several orders of magnitude smaller if it isn't a normal table) but that gives me a very annoying error: Can't reopen table
Some research leads me to this bug report but the folks over at MySQL don't seem to care that such a basic feature (using a table more than once) does not work with temporary tables. I'm running into a lot of scalability problems with this issue.
Is there any viable workaround that does not require me to manage potentially lots of temporary but very real tables or make me maintain a huge table with all the data in it?
Kind regards, Kris
[additional]
The GROUP_CONCAT answer does not work in my situation because my conditions are multiple columns in specific order, it would make ORs out of what I need to be ANDs. However, It did help me solve an earlier problem so now the table, temp or not, is no longer required. We were just thinking too generic for our problem. The entire application of filters has now been brought back from around a minute to well under a quarter of a second.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(8)
一个简单的解决方案是复制临时表。 如果表相对较小(临时表经常出现这种情况),则效果很好。
A simple solution is to duplicate the temporary table. Works well if the table is relatively small, which is often the case with temporary tables.
是的,MySQL 文档 说:“你不能在同一查询中多次引用
TEMPORARY
表。”这是一个应该找到相同行的替代查询,尽管匹配行的所有条件不会位于单独的列中,但它们将位于以逗号分隔的列表中。
Right, the MySQL docs say: "You cannot refer to a
TEMPORARY
table more than once in the same query."Here's an alternative query that should find the same rows, although all the conditions of matching rows won't be in separate columns, they'll be in a comma-separated list.
我通过创建一个永久的“临时”表并将 SPID(抱歉,我来自 SQL Server)作为表名的后缀来解决这个问题,以创建一个唯一的表名。 然后创建动态 SQL 语句来创建查询。 如果发生任何问题,该表将被删除并重新创建。
我希望有更好的选择。 来吧,MySQL 开发人员。 “bug”/“功能请求”自 2008 年以来一直开放! 似乎遇到的所有“错误”都在同一条船上。
I got around this by creating a permanent "temporary" table and suffixing the SPID (sorry, i'm from SQL Server land) to the table name, to make a unique table name. Then creating dynamic SQL statements to create the queries. If anything bad happens, the table will be dropped and recreated.
I'm hoping for a better option. C'mon, MySQL Devs. The 'bug'/'feature request' has been open since 2008! Seems like all the 'bugs' 've encountered are in the same boat.
如果切换到 MariaDB(MySQL 的一个分支)是可行的——这个烦恼从版本 10.2.1 开始就得到了修复:https://jira.mariadb.org/browse/MDEV-5535。
If switching to MariaDB (a fork of MySQL) is feasible -- this annoyance is fixed there as of version 10.2.1: https://jira.mariadb.org/browse/MDEV-5535.
就我个人而言,我只会将其设为永久桌子。 您可能希望为这些表创建一个单独的数据库(大概它们需要唯一的名称,因为可以一次完成许多查询),也允许明智地设置权限(您可以在数据库上设置权限;您可以' t 设置表通配符的权限)。
然后你还需要一个清理工作来偶尔删除旧的(MySQL 可以方便地记住表的创建时间,所以你可以用它来计算何时需要清理)
Personally I'd just make it a permanent table. You might want to create a separate database for these tables (presumably they'll need unique names as lots of these queries could be done at once), also to allow permissions to be set sensibly (You can set permissions on databases; you can't set permissions on table wildcards).
Then you'd also need a cleanup job to remove old ones occasionally (MySQL conveniently remembers the time a table was created, so you could just use that to work out when a clean up was required)
您可以通过创建一个永久表(稍后将其删除)来解决这个问题,或者只创建两个具有相同数据的单独临时表
You can get around it by either making a permanent table, which you will remove afterwards, or just make 2 separate temp tables with the same data
这里是关于这个问题的 MYSQL 文档。 我使用重复的临时表,如上面的一些答案,但是,您可能会遇到 CTE 合适的情况!
https://dev.mysql.com/doc/ refman/8.0/en/temporary-table-problems.html
Here are the MYSQL docs about this issue. I use duplicate temporary tables like some of the answers above, however, you may have a situation where a CTE is appropriate!
https://dev.mysql.com/doc/refman/8.0/en/temporary-table-problems.html
我能够将查询更改为永久表,这为我解决了这个问题。 (更改了 MicroStrategy 中的 VLDB 设置,临时表类型)。
I was able to change the query to a permanent table and this fixed it for me. ( changed the VLDB settings in MicroStrategy, temporary table type).