使用大型 WHERE IN 时,MariaDB 崩溃

问题描述 投票:0回答:2

我有一个旧项目,正在尝试将其升级到较新版本的 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
mysql mariadb-10.5
2个回答
1
投票

解决您问题的一个方法是更改您的设计/方法,这样您就不会出现包含 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;

0
投票

CREATE INDEX index_sales ON sales(上下文);

创建索引,以便更快地检索数据并减少资源。

© www.soinside.com 2019 - 2024. All rights reserved.