2012-04-25 76 views
3

我正在使用MySQL 5.5。我有一个查询(全文)使用子查询。为了提高性能和我正在使用分页的事实,我使用LIMIT来限制结果的数量。优化计数并选择查询

SELECT * 
FROM ( 
    SELECT id, type, type_id, content, MATCH(content) AGAINST('john') as relevance, IFNULL (parent_type, UUID()) as parent_type, IFNULL(parent_id, UUID()) as parent_id 
    FROM search_index 
    WHERE MATCH(content) AGAINST('john*' IN BOOLEAN MODE) GROUP BY parent_type, parent_id) as search 
GROUP BY search.type, search.type_id DESC LIMIT 10; 

除此之外,我需要发回每个搜索查询的例子(50000)的可能结果的总数。要得到计数,我正在使用:

SELECT COUNT(*) FROM(
    SELECT * 
    FROM ( 
     SELECT id, type, type_id, content, MATCH(content) AGAINST('john') as relevance, IFNULL (parent_type, UUID()) as parent_type, IFNULL(parent_id, UUID()) as parent_id 
     FROM search_index 
     WHERE MATCH(content) AGAINST('john*' IN BOOLEAN MODE) GROUP BY parent_type, parent_id) as search 
    GROUP BY search.type, search.type_id) as count; 

虽然这确实让我有些不安。下面是计数查询的解释:

enter image description here

search_indexcontent一个全文索引。 search_index_no_ft是除了contentid以外的所有列的索引。 id上有一个主键。

有没有更好的方法来做到这一点,也许是一种优化这种方式?或者,有没有办法将2个查询(计数和搜索)合并为1?

+0

你真的需要确切数量的比赛吗?谷歌必须有一个原因显示只有估计... – piotrm 2012-04-25 07:36:37

+0

我需要确切的匹配数量来生成在大多数情况下工作的分页,例如,当过滤和搜索用户列表等。如果这是一个普通的网站,因为数据量如此之大以至于用户永远无法完成全部搜索,所以我对估计感到满意。所以是的,我需要一个完全匹配的用例。 – F21 2012-04-25 08:20:52

+0

无论如何,如果你让他们这样做,有些用户会试图通过所有这些,滥用基于限制的网站中的最高偏移量是一种常见的DOS攻击类型。 – piotrm 2012-04-25 08:28:09

回答

0

您是否尝试过使用SQL_CALC_FOUND_ROWS?它的工作原理是这样的:

SELECT SQL_CALC_FOUND_ROWS some_fields FROM table WHERE xxx LIMIT 10; 
SELECT FOUND_ROWS(); 

唯一的限制是您必须在第一个查询后立即执行第二个查询。
更多在mysql文档:http://dev.mysql.com/doc/refman/5.0/en/information-functions.html#function_found-rows
不知道它将如何表现与concurnt查询,所以你将不得不检查这一点。

+0

对不起,我刚刚意识到我在我的问题中犯了一个致命的错误。我需要返回搜索可能行的总数以及由LIMIT设置的行的子集。我想要的效果与搜索引擎相似:'显示10000个可能结果中的10个'和前10个结果等等(取决于用户所在的页面)。 – F21 2012-04-25 07:06:20