MySQL数据库上的其他列上的ORDER BY的全文搜索速度非常慢

MySQL数据库上的其他列上的ORDER BY的全文搜索速度非常慢,mysql,full-text-search,Mysql,Full Text Search,我一直在处理MySQL数据库中InnoDB表的查询。 我需要基于两个文本字段的全文搜索来查找订单,其中包含json编码文本中的订单和客户详细信息。 以下是表架构: +--------------+------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +--------------+------------

我一直在处理MySQL数据库中InnoDB表的查询。 我需要基于两个文本字段的全文搜索来查找订单,其中包含json编码文本中的订单和客户详细信息。 以下是表架构:

+--------------+------------+------+-----+---------+----------------+
| Field        | Type       | Null | Key | Default | Extra          |
+--------------+------------+------+-----+---------+----------------+
| id           | int(11)    | NO   | PRI | NULL    | auto_increment |
| user_id      | int(11)    | NO   | MUL | NULL    |                |
| comment      | text       | NO   |     | NULL    |                |
| modified     | datetime   | NO   |     | NULL    |                |
| created      | datetime   | NO   | MUL | NULL    |                |
| items        | mediumtext | NO   | MUL | NULL    |                |
| addressinfo  | text       | NO   |     | NULL    |                |
+--------------+------------+------+-----+---------+----------------+
+--------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table  | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+--------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| orders |          0 | PRIMARY  |            1 | id          | A         |       69144 |     NULL | NULL   |      | BTREE      |         |               |
| orders |          1 | user_id  |            1 | user_id     | A         |       45060 |     NULL | NULL   |      | BTREE      |         |               |
| orders |          1 | created  |            1 | created     | A         |       69240 |     NULL | NULL   |      | BTREE      |         |               |
| orders |          1 | search   |            1 | items       | NULL      |       69240 |     NULL | NULL   |      | FULLTEXT   |         |               |
| orders |          1 | search   |            2 | addressinfo | NULL      |       69240 |     NULL | NULL   |      | FULLTEXT   |         |               |
+--------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
该表大约有150.000行。 它在items和addressinfo列上有一个全文索引

问题来了:

SELECT 
  id
FROM 
  orders 
WHERE 
  MATCH (items, addressinfo) AGAINST (
    '+simon* +white* ' IN BOOLEAN MODE
  ) 
ORDER BY 
  id DESC 
LIMIT 
20
这是解释结果:

+----+-------------+--------+------------+----------+---------------+--------+---------+-------+------+----------+---------------------------------------------------+
| id | select_type | table  | partitions | type     | possible_keys | key    | key_len | ref   | rows | filtered | Extra                                             |
+----+-------------+--------+------------+----------+---------------+--------+---------+-------+------+----------+---------------------------------------------------+
|  1 | SIMPLE      | orders | NULL       | fulltext | search        | search | 0       | const |    1 |   100.00 | Using where; Ft_hints: no_ranking; Using filesort |
+----+-------------+--------+------------+----------+---------------+--------+---------+-------+------+----------+---------------------------------------------------+
在大型结果集上,在标准LAMP虚拟机上处理查询大约需要30秒

如果不按id DESC排序,查询的处理速度将在0.6秒左右加快

ORDER BY id DESC 解释结果中唯一的区别是在更快的查询中缺少“使用文件排序”。测量查询时,98%的处理时间(27秒)用于“创建排序索引”

是否有任何方法可以在合理的处理时间(少于一秒钟)内使用ORDER BY在此表上进行全文搜索

我已经尝试过不同的方法,例如将order by列放入全文索引(text_id作为text列),但没有成功。 从这里开始的方法:也不是更快

由于应用程序在共享主机上运行,我在优化MySQL ini值或内存值方面非常有限


非常感谢

使用传递的表可能会获得一些时间。 试试看

查询

SELECT
 orders.id
FROM (
  SELECT 
    id  
  FROM 
    orders 
  WHERE 
    MATCH (items, addressinfo) AGAINST (
      '+simon* +white* ' IN BOOLEAN MODE
    )  
) 
  AS 
    orders_match
INNER JOIN
 orders 
ON
 orders_match.id = orders.id

ORDER BY
 orders.id DESC

LIMIT 20

谢谢这确实节省了大约6秒,但不幸的是,这仍然是22秒:/我需要在2秒或3秒以下。也许在那个前提下是不可能的?!您有一个常见的选择:规范化数据。关系数据库最适合于结构化数据(“sql”中的“s”代表“结构化”)。此外,全文索引也在稀有词上蓬勃发展。Json数据是非结构化数据。所以,虽然很容易储存,但评估起来却很困难(试着列出你上个月销售的所有产品)。例如,如果您正在寻找“怀特先生”,只需查找您知道包含(sur)姓名的栏目,比查找产品(“白袜子”)或地址(“白宫”)要快得多。由于列表较短,也可以按的顺序进行优化(无全文索引)。如果这实际上“只是”一个数据转储(并且您以结构化的方式在其他地方拥有数据,或者不需要以搜索以外的任何方式对其进行评估),您可以(可能只是额外)使用不同的数据库/搜索引擎,如elasticsearch、solr或sphinx(这是一个没有任何特定顺序的不完整列表)。他们专门搜索大量(非结构化)数据,因此这可能是比关系数据库更好的选择。谢谢你的回答。它实际上只是一个数据转储,实际上是制作时完整订单的副本。我可以使用相应的表搜索文章和客户数据,但我希望使用全文索引搜索单个文本列(大多数情况下非常快)会更容易、更快。我没有意识到全文和排序方式的问题。嗯,这取决于你是如何搜索的。全文索引有它的用途,可以是一个非常有用的工具。缺点是您无法将其与其他索引组合,因此它必须在任何位置返回包含关键字的所有内容,然后对其进行排序,然后将其限制为20。这是非常非常有效的,如果你在一个专栏中寻找稀有的单词(因为MySQL中的任何其他方法都需要一个完整的表格扫描),但是如果每个人都买白袜子的话,效果就会变差。一个完整的表扫描(按id排序)要高效得多,因为它可以在找到20行后立即停止。好的,再次感谢。看来我得另找解决办法了。但是很好地理解了mysql中全文搜索的缺点。