Mysql 多个动态查找集合中的查找
因此,在我的编程语言中有这样一个数组:Mysql 多个动态查找集合中的查找,mysql,sql,Mysql,Sql,因此,在我的编程语言中有这样一个数组: $animalsToSearch = ['fox', 'cat', 'dog']; 我有一个MySQL数据库表,如下所示: id | value ----+---------------- 1 | dog,elephant 2 | cat,dog 3 | spider,fox,cat 4 | cat 5 | dog,rabit 不幸的是,我还不能将表更改为更具关系性的表 我想从数据库value列中提取数组中的一个项存在的次数。现在
$animalsToSearch = ['fox', 'cat', 'dog'];
我有一个MySQL数据库表,如下所示:
id | value
----+----------------
1 | dog,elephant
2 | cat,dog
3 | spider,fox,cat
4 | cat
5 | dog,rabit
不幸的是,我还不能将表更改为更具关系性的表
我想从数据库value
列中提取数组中的一个项存在的次数。现在,最明显的方法是:
<?php
$count = [];
foreach (['fox', 'cat', 'dog'] as $animal) {
$count[$animal] = some_function_that_gets_the_data($animal);
}
ysth的解决方案
解释'd
id select_type table partitions type possible_keys key key_len ref rows filtered Extra
1 PRIMARY <derived2> NULL ALL NULL NULL NULL NULL 2 100.00 Using temporary; Using filesort
1 PRIMARY animal NULL ALL NULL NULL NULL NULL 1,879,296 100.00 Using where; Using join buffer (Block Nested Loop)
2 DERIVED NULL NULL NULL NULL NULL NULL NULL NULL NULL No tables used
3 UNION NULL NULL NULL NULL NULL NULL NULL NULL NULL No tables used
id选择\u类型表分区类型可能的\u键键\u len ref行过滤额外
1主空所有空2 100.00使用临时;使用文件排序
1主要动物空所有空1879296 100.00使用where;使用联接缓冲区(块嵌套循环)
2个派生空值未使用表
3 UNION NULL未使用任何表
根据您的列表加入:
select animallist.animal, count(*) as times
from (
select 'fox' as animal union all select 'cat' union all select 'dog'
) animallist
join animal on find_in_set(animallist.animal, animal.value)
group by animallist.animal
你可以试着强迫它只阅读动物一次,我不知道这会让它更快还是更慢:
select straight_join animallist.animal, count(*) as times
from animal on find_in_set(animallist.animal, animal.value)
join (
select 'fox' as animal union all select 'cat' union all select 'dog'
) animallist
group by animallist.animal
传统索引无法帮助改进FIND\u IN_SET()
的性能,就像索引无法帮助改进SUBSTRING()
或like
的通配符一样。性能永远不会好,而且随着表的增大,性能会变得更差
但全文索引可以有所帮助
ALTER TABLE animals ADD FULLTEXT INDEX (value);
mysql> select * from animals where match(value) against ('rabbit' in boolean mode);
+----+--------------+
| id | value |
+----+--------------+
| 5 | doggy,rabbit |
+----+--------------+
1 row in set (0.00 sec)
mysql> select * from animals where match(value) against ('rabbit doggy' in boolean mode);
+----+----------------+
| id | value |
+----+----------------+
| 5 | doggy,rabbit |
| 1 | doggy,elephant |
| 2 | kittycat,doggy |
+----+----------------+
在我的测试中,我让所有动物的名字至少有4个字符,因为默认的ft\u min\u word\u len
是4个字符。短于此的单词不会被全文索引索引
阅读上的章节了解更多信息。是的,有更好的方法。不要在SQL中存储逗号分隔的值。使用一个单独的表,每个值一行。我担心你错过了我的评论“不幸的是,我无法将表更改为更相关的(但)。”这是我从以前的开发人员那里继承的系统。有时我认为有一个人在公司之间漫游,破坏数据库,让其他倒霉的开发人员“继承”他的演讲很有趣。不过,我必须按动物添加分组
,才能将其分组。唯一的问题是它需要很长时间运行(2秒),而我的原始帖子查询大约需要30毫秒:(对不起,忘记了。再过2秒,explain select…
show是什么?我已经将它添加到了我的原始帖子中(为了便于阅读,还以逗号添加到180万的数字中)。添加了一个可选的连接类型no将允许find_in_set()执行除表扫描以外的任何操作。无论使用哪种联接类型,性能都将非常糟糕。
ALTER TABLE animals ADD FULLTEXT INDEX (value);
mysql> select * from animals where match(value) against ('rabbit' in boolean mode);
+----+--------------+
| id | value |
+----+--------------+
| 5 | doggy,rabbit |
+----+--------------+
1 row in set (0.00 sec)
mysql> select * from animals where match(value) against ('rabbit doggy' in boolean mode);
+----+----------------+
| id | value |
+----+----------------+
| 5 | doggy,rabbit |
| 1 | doggy,elephant |
| 2 | kittycat,doggy |
+----+----------------+