0

我有一个旧项目,我正在尝试升级到新版本的 SQL。它目前正在运行 MySql 5.5,并且运行良好。我已将 som 测试数据迁移到 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 范围 定义_respondent_context,respondent_id definition_respondent_context 12 824 使用索引条件;使用临时的;使用文件排序
2 衍生的 s2 eq_ref 定义_respondent_context,respondent_id definition_respondent_context 12 常量,数据库名称.s1.respondent_id,常量 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
4

1 回答 1

1

解决您的问题的一种方法是更改​​您的设计/方法,以便您没有WHERE IN (...)包含 500-1000 个项目的条款。一方面,您是否会让某些应用程序将如此多的参数传递回您的数据库实例是值得怀疑的。因此,假设这些数据不是来自外部,那么应该可以将其保存在单独的表中。假设您为此有两个表,则您的查询可能变为:

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;
于 2021-02-25T08:54:07.600 回答