我有一个旧项目,正在尝试将其升级到较新版本的 SQL。它目前运行的是 MySql 5.5 并且运行良好。我已将一些测试数据迁移到 MariaDB 10.5.9,但是当我尝试运行查询(在 MySql 5.5 上运行良好)时,MariaDB 崩溃了。
查询相当大,并且广泛使用 WHERE IN。目前,我无法遗憾地重构查询,因此我正在尝试找出导致崩溃的原因。
它有 3 个“WHERE IN”。第一个是 24 个项目,第二个是 696 个项目,第三个是 2 个项目。如果我从第一个或第二个 WHERE IN 中仅删除一个项目,它会立即返回数据。
answers
表是 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 | 选择类型 | 桌子 | 类型 | 可能的键 | 键 | key_len | 参考 | 行 | 额外 |
---|---|---|---|---|---|---|---|---|---|
1 | 小学 | 全部 | 824 | 临时使用;使用文件排序 | |||||
2 | 派生 | s1 | 范围 | definition_respondent_context,respondent_id | definition_respondent_context | 12 | 824 | 使用索引条件;使用临时的;使用文件排序 | |
2 | 派生 | s2 | eq_ref | definition_respondent_context,respondent_id | definition_respondent_context | 12 | const,database_name.s1.respondent_id,const | 1 |
编辑:我设法通过在定义表上使用联接来使其工作
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
解决您问题的一个方法是更改您的设计/方法,这样您就不会出现包含 500-1000 个项目的
WHERE IN (...)
子句。 一方面,您是否会让某个应用程序将如此多的参数传递回您的数据库实例是值得怀疑的。 因此,假设这些数据不是来自外部,那么应该可以将其维护在单独的表中。 假设您有两个表,那么您的查询可能会变成:
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;
CREATE INDEX index_sales ON sales(上下文);
创建索引,以便更快地检索数据并减少资源。