MariaDB 在使用大型 WHERE IN 时崩溃
MariaDB crashes when using large WHERE IN
我有一个旧项目,我正在尝试升级到更新版本的 SQL。目前是 运行 MySql 5.5 并且工作正常。我已经将 som 测试数据迁移到 MariaDB 10.5.9,但是当我尝试 运行 查询(在 MySql 5.5 上运行良好)时,MariaDB 崩溃了。
查询量很大,广泛使用WHERE IN。目前我无法遗憾地重构查询,所以我试图找出导致崩溃的原因。
它有 3 个 WHERE IN。第一个是 24 个项目,第二个是 696 个,第三个是 2 个。如果我只从第一个或第二个 WHERE IN 中删除一个项目,它会立即工作 returns 数据。 answers
table 是 MyISAM
我遇到的错误
SQL Error [08S01]: Communications link failure
The last packet sent successfully to the server was 0 milliseconds ago. The driver has not received any packets from the server.
和查询
SELECT
definition_id,
answer AS value
FROM
answers
WHERE
definition_id IN (...)
AND respondent_id in (...)
AND context IN (1, 0)
LIMIT 50
我已经尝试将 max_allowed_packet
更改为更高的值(在 5.5 中为 16MB),但遗憾的是它没有任何改变。
EXPLAIN SQL_NO_CACHE 的结果(如果我删除了 WHERE IN 中的大量数据以避免崩溃)
id
select_type
table
type
possible_keys
key
key_len
ref
rows
Extra
1
PRIMARY
ALL
824
Using temporary; Using filesort
2
DERIVED
s1
range
definition_respondent_context,respondent_id
definition_respondent_context
12
824
Using index condition; Using temporary; Using filesort
2
DERIVED
s2
eq_ref
definition_respondent_context,respondent_id
definition_respondent_context
12
const,database_name.s1.respondent_id,const
1
编辑:我设法通过对定义 table
使用连接使其工作
SELECT
a.definition_id,
a.answer AS value
FROM
answers AS a
JOIN definitions AS d ON a.definition_id = d.id
WHERE
d.id IN (...)
AND a.respondent_id in (...)
AND a.context IN (1, 0)
LIMIT 50
您的问题的一个解决方案是更改您的 design/approach,这样您就没有包含 500-1000 个项目的 WHERE IN (...)
子句。一方面,您是否会让某个应用程序将如此多的参数传递回您的数据库实例是值得怀疑的。因此,假设此数据不是来自外部,那么应该可以将其维护在单独的 table 中。假设您为此有两个 table,您的查询可能会变成:
SELECT a.definition_id, a.answer AS value
FROM answers a
INNER JOIN definitions d
ON d.id = a.definition_id
INNER JOIN respondents r
ON r.id = a.respondent_id
WHERE
context IN (1, 0)
-- ORDER BY <something>
LIMIT 50;
我有一个旧项目,我正在尝试升级到更新版本的 SQL。目前是 运行 MySql 5.5 并且工作正常。我已经将 som 测试数据迁移到 MariaDB 10.5.9,但是当我尝试 运行 查询(在 MySql 5.5 上运行良好)时,MariaDB 崩溃了。
查询量很大,广泛使用WHERE IN。目前我无法遗憾地重构查询,所以我试图找出导致崩溃的原因。
它有 3 个 WHERE IN。第一个是 24 个项目,第二个是 696 个,第三个是 2 个。如果我只从第一个或第二个 WHERE IN 中删除一个项目,它会立即工作 returns 数据。 answers
table 是 MyISAM
我遇到的错误
SQL Error [08S01]: Communications link failure
The last packet sent successfully to the server was 0 milliseconds ago. The driver has not received any packets from the server.
和查询
SELECT
definition_id,
answer AS value
FROM
answers
WHERE
definition_id IN (...)
AND respondent_id in (...)
AND context IN (1, 0)
LIMIT 50
我已经尝试将 max_allowed_packet
更改为更高的值(在 5.5 中为 16MB),但遗憾的是它没有任何改变。
EXPLAIN SQL_NO_CACHE 的结果(如果我删除了 WHERE IN 中的大量数据以避免崩溃)
id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
---|---|---|---|---|---|---|---|---|---|
1 | PRIMARY | ALL | 824 | Using temporary; Using filesort | |||||
2 | DERIVED | s1 | range | definition_respondent_context,respondent_id | definition_respondent_context | 12 | 824 | Using index condition; Using temporary; Using filesort | |
2 | DERIVED | s2 | eq_ref | definition_respondent_context,respondent_id | definition_respondent_context | 12 | const,database_name.s1.respondent_id,const | 1 |
编辑:我设法通过对定义 table
使用连接使其工作SELECT
a.definition_id,
a.answer AS value
FROM
answers AS a
JOIN definitions AS d ON a.definition_id = d.id
WHERE
d.id IN (...)
AND a.respondent_id in (...)
AND a.context IN (1, 0)
LIMIT 50
您的问题的一个解决方案是更改您的 design/approach,这样您就没有包含 500-1000 个项目的 WHERE IN (...)
子句。一方面,您是否会让某个应用程序将如此多的参数传递回您的数据库实例是值得怀疑的。因此,假设此数据不是来自外部,那么应该可以将其维护在单独的 table 中。假设您为此有两个 table,您的查询可能会变成:
SELECT a.definition_id, a.answer AS value
FROM answers a
INNER JOIN definitions d
ON d.id = a.definition_id
INNER JOIN respondents r
ON r.id = a.respondent_id
WHERE
context IN (1, 0)
-- ORDER BY <something>
LIMIT 50;