使用fulltextindex和其他where条件进行高效查询

时间:2012-08-13 13:11:27

标签: mysql indexing full-text-search

我的问题如下:

我有一个包含 23百万行的表mailmessage(1年的数据)。
以下是此表的重要字段

  • id(bigint)
  • msgtimeutc(bigint)
  • subject(tinytext)
  • body(text)
  • 要显示的其他一些数据

我在这张桌子上有一个全文索引:
 CREATE FULLTEXT INDEX mailmessage_fulltext ON mailmessage (body,subject)

我需要在msgtimeutc上执行请求在正文和主题中搜索文字并按日期时间缩小,如下所示:

SELECT M.some_data  
FROM mailmessage M 
WHERE M.MSGTIMEUTC >= 1343651965 AND M.MSGTIMEUTC <= 1344170365 
AND ( MATCH (M.BODY,M.SUBJECT) AGAINST ('test')); 

mySQL

  • 不能同时使用2个索引(msgtimeutc和fulltextindex上的索引)。所以我的查询结束了在msgtimeutc上进行全表扫描
  • 我不能在全文索引中包含msgtimeutc,因为它是一个bigint而我正在上面或下面做它

因此查询占用的时间太长(和I / O)!

我想要像这样做一个 intersect (示例代码没有经过测试)

SELECT M1.some_data FROM mailmessage M1 
WHERE M1.MSGTIMEUTC >= 1343651965 AND M1.MSGTIMEUTC <= 1344170365 
INTERSECT
SELECT M2.some_data FROM mailmessage M2 
WHERE ( MATCH (M2.BODY,M2.SUBJECT) AGAINST ('test')); 

解释(抱歉滚动条):

+----+-------------+-------+----------+---------------------------------+----------------------+---------+------+------+-------------+ 
| id | select_type | table | type     | possible_keys                   | key                  | key_len | ref  | rows | Extra       | 
+----+-------------+-------+----------+---------------------------------+----------------------+---------+------+------+-------------+ 
|  1 | SIMPLE      | M     | fulltext | msgtimeutc,mailmessage_fulltext | mailmessage_fulltext | 0       |      |    1 | Using where |
+----+-------------+-------+----------+---------------------------------+----------------------+---------+------+------+-------------+ 

但它在mySQL上不存在

其他请求(如下面的2)也在进行全表扫描

SELECT M.some_data 
FROM mailmessage M 
WHERE 
M.id in ( 
   select m2.id from mailmessage m2 use index(mailmessage_fulltext)
   where (MATCH (m2.BODY,m2.SUBJECT) AGAINST ('test')) 
) 
AND M.MSGTIMEUTC >= 1343651965 AND M.MSGTIMEUTC <= 1344170365;

SELECT M1.ATTACHMENTCOUNT AS ATCH_COUNT 
FROM mailmessage AS M1 
INNER JOIN mailmessage AS M2 ON M1.id = M2.id 
WHERE (M1.MSGTIMEUTC >= 1343651965 AND M1.MSGTIMEUTC <= 1344170365) 
AND (MATCH (M2.BODY,M2.SUBJECT) AGAINST ('test'))

两个查询解释计划只显示我使用的一个索引(全文)

所以我可能最终按日期过滤programmaticaly行...但我更喜欢(关于卷)数据库解决方案

有什么想法吗?

1 个答案:

答案 0 :(得分:1)

从最新的MySQL版本开始,无法将全文索引与另一个

组合在一起

http://dev.mysql.com/doc/refman/5.6/en/index-merge-optimization.html

  

索引合并不适用于全文索引。我们计划在未来的MySQL版本中扩展它以涵盖这些内容。

您可以尝试使用临时表解决您的问题:

CREATE TEMPORARY TABLE my_search 
  (FULLTEXT INDEX mailmessage_fulltext(body,subject))         
SELECT M.some_data  
FROM mailmessage M 
WHERE M.MSGTIMEUTC >= 1343651965 AND M.MSGTIMEUTC <= 1344170365

然后将其与查询匹配

SELECT M.some_data  
FROM my_search M 
WHERE ( MATCH (M.BODY,M.SUBJECT) AGAINST ('test'));

请记住,对于此解决方案,实际表中的全文索引变得完全没用。