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,…)之一
Select * from table1 t1 inner join table2 t2 on t1.col_a=t2.col_a WHERE t2.value_of_sub_d=2
一种可能的优化是将
[column d]
定义为typeSET
。作为:
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')
);