mySQL 全文索引减慢查询速度
mySQL full text index slows query
我有一个包含两列的 table:"users" 有一个全文索引,"x" 是一个简单的 int 列。 table 包含将近 200 万个条目。使用 match...against
到 select 包含特定用户的行 returns 快速。
在 ~3 秒内按 x 的值(未编入索引)搜索 returns。
但是,当我将两者结合起来时,查询需要大约 9 秒!如果有的话,我希望组合查询花费的时间少得多,因为全文索引将可能的行减少了一个数量级。即使忘记全文索引并使用 like "%___%"
也更快!
这是怎么回事?我该如何解决?
mySQL 输出包含在下面:
mysql> desc testing;
+-------+--------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+--------------+------+-----+---------+-------+
| users | varchar(120) | YES | MUL | NULL | |
| x | int(11) | YES | | NULL | |
+-------+--------------+------+-----+---------+-------+
2 rows in set (0.00 sec)
mysql> select count(*) from testing;
+----------+
| count(*) |
+----------+
| 1924272 |
+----------+
1 row in set (3.56 sec)
mysql> select count(*) from testing where match(users) against("shy");
+----------+
| count(*) |
+----------+
| 149019 |
+----------+
1 row in set (0.42 sec)
mysql> select count(*) from testing where x>0;
+----------+
| count(*) |
+----------+
| 1924272 |
+----------+
1 row in set (3.62 sec)
mysql> select count(*) from testing where match(users) against("shy") and x>0;
+----------+
| count(*) |
+----------+
| 149019 |
+----------+
1 row in set (8.82 sec)
mysql> select count(*) from testing where users like "%shy%" and x>0;
+----------+
| count(*) |
+----------+
| 149019 |
+----------+
1 row in set (3.57 sec)
考虑使用子查询,例如
select count(*) from (
select *
from testing
where match(users) against("shy")
) shy_results
where x>0;
始终检查 innodb_buffer_pool_size
的值并根据系统的功能和软件要求进行调整。这意味着不要给 MySQL 比你拥有的更多的 RAM :)
如果索引不适合内存,MySQL 将从磁盘读取它,将您限制在硬盘驱动器的速度上。如果您使用的是 SSD,这可能是 ok-ish,但在机械驱动器上它慢得像蜗牛。
如果索引不能放入 RAM 中,它们就没有那么有用了。
我有一个包含两列的 table:"users" 有一个全文索引,"x" 是一个简单的 int 列。 table 包含将近 200 万个条目。使用 match...against
到 select 包含特定用户的行 returns 快速。
在 ~3 秒内按 x 的值(未编入索引)搜索 returns。
但是,当我将两者结合起来时,查询需要大约 9 秒!如果有的话,我希望组合查询花费的时间少得多,因为全文索引将可能的行减少了一个数量级。即使忘记全文索引并使用 like "%___%"
也更快!
这是怎么回事?我该如何解决?
mySQL 输出包含在下面:
mysql> desc testing;
+-------+--------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+--------------+------+-----+---------+-------+
| users | varchar(120) | YES | MUL | NULL | |
| x | int(11) | YES | | NULL | |
+-------+--------------+------+-----+---------+-------+
2 rows in set (0.00 sec)
mysql> select count(*) from testing;
+----------+
| count(*) |
+----------+
| 1924272 |
+----------+
1 row in set (3.56 sec)
mysql> select count(*) from testing where match(users) against("shy");
+----------+
| count(*) |
+----------+
| 149019 |
+----------+
1 row in set (0.42 sec)
mysql> select count(*) from testing where x>0;
+----------+
| count(*) |
+----------+
| 1924272 |
+----------+
1 row in set (3.62 sec)
mysql> select count(*) from testing where match(users) against("shy") and x>0;
+----------+
| count(*) |
+----------+
| 149019 |
+----------+
1 row in set (8.82 sec)
mysql> select count(*) from testing where users like "%shy%" and x>0;
+----------+
| count(*) |
+----------+
| 149019 |
+----------+
1 row in set (3.57 sec)
考虑使用子查询,例如
select count(*) from (
select *
from testing
where match(users) against("shy")
) shy_results
where x>0;
始终检查 innodb_buffer_pool_size
的值并根据系统的功能和软件要求进行调整。这意味着不要给 MySQL 比你拥有的更多的 RAM :)
如果索引不适合内存,MySQL 将从磁盘读取它,将您限制在硬盘驱动器的速度上。如果您使用的是 SSD,这可能是 ok-ish,但在机械驱动器上它慢得像蜗牛。
如果索引不能放入 RAM 中,它们就没有那么有用了。