【发布时间】:2016-03-12 00:29:21
【问题描述】:
我在 Amazon RDS 上运行了 MySQL V5.6.23。其中有一个名为product_details 的 InnoDB 表,其中包含大约 10 个列,这些列都为精确匹配(日期、数字、文本等)编制了索引。然后我有一个单独的product_name 字段,我已经在该字段上放置了 FULLTEXT 索引。我还有很多其他领域我们没有搜索。
该表目前有 150M 行,我们每晚增加大约 3-5M,并且每晚更新另外 10-20M。在晚上运行这些插入/更新后,FULLTEXT 索引似乎从内存中删除(不确定这到底是怎么回事)。
当我第一次运行“blue ford taurus”的查询时,查询可能需要几分钟时间。我第二次运行它时,即使不是几百毫秒,也只有几秒钟。如果我在新数据处理完成后运行OPTIMIZE TABLE product_details;,那么我测试的几乎每个搜索都尽可能快。这需要几个小时才能运行OPTIMIZE TABLE(因为我认为它正在重写整个表(和索引?)?!?!
我曾考虑过创建一个“预热”脚本,该脚本只会针对来自用户的常见查询进行处理,但我对正在发生的事情没有很好的心理模型,所以我不知道这是什么会热身。搜索“blue ford taurus”似乎不仅加快了查询速度,但我不明白为什么。
问题
在每晚加载新数据后,如何正确加热这些索引?此表支持最终用户每天早上搜索的 Web 应用程序。
我如何知道保存索引需要哪些内存要求?
评论
- 我正计划将这一切转移到 Elasticsearch(或类似的),在那里我有很多搜索经验。我不熟悉 MySQL 作为 FULLTEXT“搜索引擎”,但目前我还是坚持使用它。
常见查询
SELECT * FROM product_details as pd
WHERE
MATCH (pd.product_name) AGAINST ('+ipod +nano' IN BOOLEAN MODE)
and pd.city_id IN (577,528,567,614,615,616,618)
ORDER BY(pd.timestamp) DESC
LIMIT 1000;
表格
CREATE TABLE `product_details` (
`product_name` text NOT NULL,
`category_name` varchar(100) NOT NULL,
`product_description` text NOT NULL,
`price` int(11) NOT NULL,
`address` varchar(200) NOT NULL,
`zip_code` varchar(30) NOT NULL DEFAULT '',
`phone` bigint(10) DEFAULT NULL,
`email` varchar(50) NOT NULL,
`state` varchar(20) NOT NULL,
`city` varchar(30) NOT NULL,
`post_id` bigint(11) NOT NULL,
`post_date` date DEFAULT NULL,
`post_time` time NOT NULL,
`updated_date` varchar(10) NOT NULL,
`updated_time` time NOT NULL,
`status` tinyint(4) NOT NULL,
`timestamp` date NOT NULL,
`new_field` tinyint(4) DEFAULT NULL,
`multiple_items` tinyint(1) NOT NULL,
`city_id` int(4) NOT NULL,
`date_changed` date DEFAULT NULL,
`latlong` varchar(100) NOT NULL,
PRIMARY KEY (`post_id`),
KEY `city_id` (`city_id`),
KEY `post_date` (`post_date`),
KEY `price` (`price`),
KEY `category_name` (`category_name`),
KEY `state` (`state`),
KEY `multiple_items` (`multiple_items`),
KEY `new_field` (`new_field`),
KEY `phone` (`phone`),
KEY `timestamp` (`timestamp`),
KEY `date_changed` (`date_changed`),
FULLTEXT KEY `product_name` (`product_name`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
上面的表状态数据实际上是针对我的 dev 表的,其中只有 18M 行。当我加载所有生产数据时,它将有 ~8 倍的数据量,这意味着 data_length 将是 ~70GB,index_length 将是 ~32GB。
【问题讨论】:
标签: mysql indexing full-text-search innodb full-text-indexing