You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

MySQL中比FIND_IN_SET更快的查询方法(逗号分隔长整型)

优化MySQL存储过程中FIND_IN_SET的查询性能

首先确保network.network_edges表的id字段存在主键索引或普通索引,这是所有优化方案生效的基础。以下是针对Azure MySQL 8.0的几种优化方案:

方案1:使用JSON_TABLE拆分逗号分隔字符串

利用MySQL 8.0原生支持的JSON_TABLE函数,将输入的逗号分隔字符串转换为临时表,通过JOIN关联原表,让查询能命中id字段的索引。

CREATE PROCEDURE `sel_network_edges_by_id`(
    IN input_ids TEXT
)
BEGIN
    SELECT ne.id, ne.gradient, ne.geoJson, ... 
    FROM network.network_edges ne
    JOIN JSON_TABLE(
        CONCAT('[', input_ids, ']'), -- 将逗号字符串转为JSON数组格式
        '$[*]' COLUMNS(id BIGINT PATH '$')
    ) AS ids ON ne.id = ids.id;
END

方案2:动态生成IN子句(预处理语句)

将输入的input_ids直接拼接为IN子句,通过预处理语句执行,让MySQL利用索引进行范围查找。注意需确保输入仅包含数字和逗号,避免SQL注入风险。

CREATE PROCEDURE `sel_network_edges_by_id`(
    IN input_ids TEXT
)
BEGIN
    -- 可选:校验输入格式,仅允许数字和逗号
    IF NOT input_ids REGEXP '^[0-9]+(,[0-9]+)*$' THEN
        SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = '输入格式无效,仅允许逗号分隔的数字';
    END IF;

    SET @sql = CONCAT(
        'SELECT id, gradient, geoJson, ... 
         FROM network.network_edges 
         WHERE id IN (', input_ids, ')'
    );
    PREPARE stmt FROM @sql;
    EXECUTE stmt;
    DEALLOCATE PREPARE stmt;
END

方案3:改用JSON数组作为输入参数

调整存储过程的输入参数为JSON数组类型,直接通过JSON_TABLE解析后关联原表,格式更规范且易于校验。

CREATE PROCEDURE `sel_network_edges_by_id`(
    IN input_ids JSON
)
BEGIN
    -- 可选:校验输入是否为非空JSON数组
    IF NOT JSON_VALID(input_ids) OR JSON_TYPE(input_ids) != 'ARRAY' THEN
        SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = '输入必须为有效的JSON数组';
    END IF;

    SELECT ne.id, ne.gradient, ne.geoJson, ... 
    FROM network.network_edges ne
    JOIN JSON_TABLE(
        input_ids,
        '$[*]' COLUMNS(id BIGINT PATH '$')
    ) AS ids ON ne.id = ids.id;
END

方案对比

  • 方案1和3:无需担心SQL注入,性能稳定,能充分利用索引,推荐优先使用。
  • 方案2:性能最优但需严格校验输入格式,适合信任输入来源的场景。

内容的提问来源于stack exchange,提问作者Liam

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.14 13:10:22