Mysql 在_SET()选项中查找_?

Mysql 在_SET()选项中查找_?,mysql,Mysql,我有一个查询,当前看起来像: SELECT [column a], [column b], [column c], [column d] FROM [table] WHERE FIND_IN_SET(2, column d) ORDER BY [column a] DESC 其中,[列d]的类型为varchar,并包含一组数字(例如,3,2,4,6,1,9)。因此,基本上我试图返回2在其数字集中的所有记录。但是,当我对上述查询执行EXPLAIN时,这是我的输出: id select_typ

我有一个查询,当前看起来像:

SELECT [column a], [column b], [column c], [column d]
FROM [table] 
WHERE FIND_IN_SET(2, column d)
ORDER BY [column a] DESC
其中,[列d]的类型为
varchar
,并包含一组数字(例如,
3,2,4,6,1,9
)。因此,基本上我试图返回
2
在其数字集中的所有记录。但是,当我对上述查询执行
EXPLAIN
时,这是我的输出:

id  select_type table   type    possible_keys   key     key_len     ref     rows        Extra
1   SIMPLE      [table] ALL     NULL            NULL    NULL        NULL    500000      Using where; Using filesort

在执行此查询期间,此查询似乎没有使用任何索引<代码>[列a]是主键,因此该列上已经有索引。是否有任何方法可以利用索引使此查询运行得更快?或者有没有其他方法可以提高此查询的性能?

备选方案:正确规范化模式


“在集合中查找”不可用,索引无法使用。

1-在这种情况下,全文索引不是一个好主意,因为: 在本例中,您搜索的字符串长度很小(1), 这是找不到的(虽然它是可配置的,但不是一个好的 (想法)

2-如果此查询比较频繁,我建议更改表的结构,如下所示:

  • 表1(a列主键、b列、c列)
  • 表2(col_a FK,d的值),其中d的值为(2,3,…)之一
在这种一对多关系中,您可以执行联接,或者从满足条件的表2中获取PK,然后从表1中选择该ID的行 例如:

Select * from table1 t1 inner join table2 t2 on t1.col_a=t2.col_a WHERE t2.value_of_sub_d=2

一种可能的优化是将
[column d]
定义为type
SET
。作为:

MySQL以数字形式存储设置值,低阶位为 与第一个集合成员对应的存储值。如果您检索到 设置值在数字上下文中,检索的值已设置位 对应于构成列值的集合成员

下面是一个简单的例子:

创建表'tbl_name`(
`id`int(11)非空自动增量,
`set_col'set('a','b','c','d')不为空,
主键(`id`),
键'set\u col\u idx'('set\u col`)
)ENGINE=InnoDB默认字符集=utf8;
插入'tbl\u name'('set\u col')值
(‘a’),
("b"),,
('c'),
("d"),,
(‘a,b’),
('a,c'),
('a,d'),
('b,c'),
('b,d'),
('c,d'),
('a,b,c'),
('a,b,d'),
('a,c,d'),
('b,c,d'),
('a,b,c,d');
指定为
set('A'、'b'、'c'、'd')
的列
set\u col
具有以下十进制和二进制值的成员:

╔════════════╦═══════════════╦══════════════╗
║ 集合成员║ 十进制值║ 二进制值║
╠════════════╬═══════════════╬══════════════╣
║     'a'║       1.║     0001║
╠════════════╬═══════════════╬══════════════╣
║     'b'║       2.║     0010║
╠════════════╬═══════════════╬══════════════╣
║     'c'║       4.║     0100║
╠════════════╬═══════════════╬══════════════╣
║     'd'║       8.║     1000║
╚════════════╩═══════════════╩══════════════╝
因此,如果需要检索值为
a、c、d
的记录,那么它是第一个、第三个和第四个成员,即
1+4+8
,即
13

如果运行查询:

您将获得:

您不需要手动了解
设置
选项的十进制值–您可以使用
求和
,例如:

╔════╦═════════════╦══════════╦═══════╦═══════════════╦═════════════╦═════════╦═══════╦══════╦══════════════════════════╗
║ 身份证件║ 选择类型║ 桌子║ 类型║ 可能的\u键║ 钥匙║ 基伦║ 裁判║ 排║ 额外的║
╠════╬═════════════╬══════════╬═══════╬═══════════════╬═════════════╬═════════╬═══════╬══════╬══════════════════════════╣
║  1.║ 主要的,重要的║ tbl_名称║ 指数║ 集合集合集合idx║ 集合集合集合idx║ 1.║ 无效的║ 15║ 在何处使用;使用索引║
╠════╬═════════════╬══════════╬═══════╬═══════════════╬═════════════╬═════════╬═══════╬══════╬══════════════════════════╣
║  1.║ 子查询║ tbl_名称║ 范围║ 集合集合集合idx║ 集合集合集合idx║ 1.║ 无效的║ 3.║ 在何处使用;使用索引║
╚════╩═════════════╩══════════╩═══════╩═══════════════╩═════════════╩═════════╩═══════╩══════╩══════════════════════════╝

那么有没有办法在
[d列]
上创建索引?我在考虑创建一个
全文
索引,因为它是
varchar
wow类型。我第一次听说sargable,你是创建wiki页面的人吗;-)@YiweiG它不会被FIND_IN_SET使用;我不知道
EXPLAIN SELECT * FROM `tbl_name` WHERE `tbl_name`.`set_col` = 13;
╔════╦═════════════╦══════════╦══════╦═══════════════╦═════════════╦═════════╦═══════╦══════╦═════════════╗
║ id ║ select_type ║ table    ║ type ║ possible_keys ║ key         ║ key_len ║ ref   ║ rows ║ Extra       ║
╠════╬═════════════╬══════════╬══════╬═══════════════╬═════════════╬═════════╬═══════╬══════╬═════════════╣
║  1 ║ SIMPLE      ║ tbl_name ║ ref  ║ set_col_idx   ║ set_col_idx ║ 1       ║ const ║ 1    ║ Using index ║
╚════╩═════════════╩══════════╩══════╩═══════════════╩═════════════╩═════════╩═══════╩══════╩═════════════╝
SELECT *
FROM `tbl_name`
WHERE `set_col` = (SELECT SUM(`set_col`)
 FROM `tbl_name`
 WHERE `set_col` IN ('a', 'c', 'd')
);