2013-06-24 138 views
1

我正在使用mysql作为数据库在php中为网站创建产品搜索系统。优化MySQL全文搜索查询?

目前我们有超过100K的产品需要搜索。由于我们的要求强度很低,我曾考虑使用内置全文本功能(Match and Against)的MySQL,而不是Sphinx或Lucene。

因此,目前我们使用MySQL内置的全文搜索功能,有人可以帮助我们优化此全文搜索查询,以获得更高的效率和更少的人头。

正如有人向我暗示,我可能没有正确使用全文语法。

CREATE TABLE结构

-- Create Table SQL for Product -- 
DROP TABLE IF EXISTS `ps_search__p`; 
CREATE TABLE IF NOT EXISTS `ps_search__p` (
    `id` int(10) unsigned NOT NULL, 
    `code` varchar(100) NOT NULL, 
    `type` varchar(100) DEFAULT NULL, 
    `name` text, 
    `keywords` text, 
    `material` text, 
    `material_def_id` int(11) unsigned DEFAULT NULL, 
    `s_type` text, 
    `s_fabric` text, 
    `price` decimal(20,6) unsigned DEFAULT NULL, 
    `build_type` varchar(12) NOT NULL, 
    `genre` varchar(12) NOT NULL DEFAULT 'p', 
    `categories` text, 
    PRIMARY KEY (`id`), 
    FULLTEXT KEY `code` (`code`,`type`,`name`,`keywords`,`material`,`s_type`,`s_fabric`,`categories`) 
) ENGINE=MyISAM DEFAULT CHARSET=latin1; 


-- Create SQL Table for S table -- 
DROP TABLE IF EXISTS `ps_search__s`; 
CREATE TABLE IF NOT EXISTS `ps_search__s` (
    `id` int(20) unsigned NOT NULL, 
    `s_id` varchar(100) NOT NULL, 
    `type` varchar(100) NOT NULL, 
    `fabric` varchar(100) DEFAULT NULL, 
    `name` varchar(100) DEFAULT NULL, 
    `price` decimal(20,6) unsigned DEFAULT NULL, 
    `genre` varchar(12) NOT NULL DEFAULT 's', 
    `categories` text, 
    PRIMARY KEY (`id`), 
    FULLTEXT KEY `s_id` (`s_id`,`type`,`fabric`,`name`,`categories`) 
) ENGINE=MyISAM DEFAULT CHARSET=latin1; 

全文搜索查询

SELECT SQL_CALC_FOUND_ROWS * FROM (
    (SELECT 
     `id`, `code`, `name`, `material`,`material_def_id`, `s_type`, `s_fabric`, `price`, `genre`, `categories`, 
     MATCH (`code`,`type`,`name`,`keywords`,`material`,`s_type`,`s_fabric`,`categories`) 
     AGAINST ('+cotton*' IN BOOLEAN MODE) AS `relevance` 
    FROM `ps_search__p` 
    WHERE 
     (MATCH (`code`,`type`,`name`,`keywords`,`material`,`s_type`,`s_fabric`,`categories`) 
     AGAINST ('+cotton*' IN BOOLEAN MODE)) 
     AND `s_type` REGEXP '.*' 
     AND `s_fabric` REGEXP '.*' 
     AND `material` REGEXP '.*' 
     AND `price` REGEXP '.*' 
     AND `categories` REGEXP '.*' 
     ) 
UNION ALL 
    (SELECT 
     `id`, `s_id`, `name`, NULL AS `material`, NULL AS `material_def_id`, `type`, `fabric`, `price`, `genre`, `categories`, 
     MATCH (`s_id`,`type`,`fabric`,`name`,`categories`) 
     AGAINST ('+cotton*' IN BOOLEAN MODE) AS `relevance` 
    FROM `ps_search__s` 
    WHERE 
     (MATCH (`s_id`,`type`,`fabric`,`name`,`categories`) 
     AGAINST ('+cotton*' IN BOOLEAN MODE)) 
     AND `type` REGEXP '.*' 
     AND `fabric` REGEXP '.*' 
     AND `price` REGEXP '.*' 
     AND IFNULL(`categories`, '') REGEXP '.*') 
) AS `tblsearch` 
ORDER BY `relevance` DESC 
LIMIT 0, 36 

并获取查询计数

SELECT FOUND_ROWS() 'recordsnum'; 

即使有一点小小的帮助也会感激不尽。

+0

有没有办法让这个查询是任何优化,使用狮身人面像,将需要不到两天,并且速度更快! – We0

+1

这些搜索条件在您的应用程序中有什么用途? 'AND s_type REGEXP'。*''他们保证打败任何索引的使用。 –

+0

噢,我的天啊,是的,请尽快用'IS NOT NULL'替换'REGEXP'。*''!或者更好的是,在这些列上添加一个“NOT NULL”约束,并完全摆脱这个测试。 – RandomSeed

回答

1

将所有测试REGEXP '.*'替换为IS NOT NULL

杠杆的全文索引,以MATCH(fabric) AGAINST ("+Cotton" IN BOOLEAN MODE) OR MATCH(fabric) AGAINST ("+Nylon" IN BOOLEAN MODE)

Normalize your database替代测试,如fabric REGEXP 'Cotton|Nylon'。列不应包含非标量值(如CSV数据)。相反,应该用新表建立一对多的关系。

+0

读完你的初步评论后,你会有同样的想法,明天会尝试,并让你知道 –