- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我已在 Amazon RDS 上运行 MySQL V5.6.23。其中有一个名为 product_details
的 InnoDB 表,其中包含大约 10 列,所有列均已建立索引以实现精确匹配(日期、数字、文本等)。然后,我有一个 product_name
字段,我已在其中添加了 FULLTEXT 索引。我还有很多其他领域我们没有搜索。
该表目前有 150M 行,我们每晚添加约 3-5M 行,并且每晚更新另外 10-20M 行。在晚上运行这些插入/更新后,全文索引似乎从内存中删除(不确定到底发生了什么)。
当我第一次运行“blue ford taurus”查询时,查询可能需要几分钟的时间。我第二次运行它时,即使不是几百毫秒,也只是几秒钟。如果我在新数据处理完成后运行OPTIMIZE TABLE Product_details;
,那么我测试的几乎每个搜索都会尽可能快。这需要几个小时来运行OPTIMIZE TABLE
(因为我认为它正在重写整个表(和索引?)?!?!
我考虑过创建一个“预热”脚本,该脚本只会包含用户的常见查询,但我对正在发生的事情没有一个好的心理模型,所以我不知道这是什么会变暖。搜索“blue ford taurus”似乎不仅仅加快了查询速度,但我不明白为什么。
问题
每晚加载新数据后,应如何正确预热这些索引?该表支持最终用户每天早上搜索的网络应用程序。
我如何知道保存索引需要多少内存?
评论
常见查询
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;
上面的表状态数据实际上是我的开发表的数据,其中只有 18M 行。当我加载所有生产数据时,它将具有约 8 倍的数据量,这意味着 data_length
将约为 70GB,index_length
将约为 32GB。
最佳答案
优化(或不优化)。是的OPTIMIZE TABLE
复制表并重建所有索引,因此需要很长时间。不要运行OPTIMIZE
;这几乎没有帮助。 (或者您看到重大变化吗?)
调整。您有多少 RAM?索引有多大? 显示表状态
。
innodb_buffer_pool_size
应约为可用 RAM 的 70%。
缩小架构会有所帮助:
DATE
和 TIME
拆分为两个字段的做法很少见city
和 city_id
。也许您应该将 city
和 state
以及 zip_code
规范化到另一个表(一个,而不是另外两个表)中。city_id
可以是 SMALLINT UNSIGNED
(2 字节:0..65535)而不是 INT SIGNED
( 4 字节)。category_name
和任何其他重复列?updated_date
是 VARCHAR
??查询中的步骤
*
的所有列。听起来该表比 RAM 大很多,所以这意味着大约 5555 次磁盘读取——可能是最慢的部分。city_id
过滤掉不需要的行。假设我们的行数减少到了 3210 行。TEXT
列,因此它将是一个 MyISAM 表,而不是一个更快的 MEMORY 表。时间戳
排序正如我希望您所看到的,大行意味着 tmp 表中的大内容。减少 *
和/或缩小列。
这是一个减少 tmp 表大小的技巧(步骤 4、5、6):
SELECT ...
FROM product_details as pd
JOIN
( SELECT post_id
FROM product_details
WHERE MATCH (product_name) AGAINST ('+ipod +nano' IN BOOLEAN MODE)
and city_id IN (577,528,567,614,615,616,618)
ORDER BY timestamp DESC
LIMIT 1000
) x USING (post_id)
ORDER BY pd.timestamp;
但是,tmp 表并不是最糟糕的部分,这需要进行第二次排序。所以,你可以尝试这个,但不要屏住呼吸。
请注意,当您运行可能受 I/O 限制的测试时,请运行两次。第二次运行将是一个更公平的比较,因为它大概没有 I/O。
另一层应该更快:
SELECT pd...
FROM
( SELECT post_id
FROM product_details
WHERE MATCH (product_name) AGAINST ('+ipod +nano' IN BOOLEAN MODE)
) AS a
JOIN product_details AS b ON b.post_id = a.post_id
WHERE b.city_id IN (577,528,567,614,615,616,618)
ORDER BY b.timestamp DESC
LIMIT 1000 ) x
JOIN product_details as pd ON pd.post_id = b.post_id
ORDER BY pd.timestamp;
INDEX(post_id, city_id, timestamp) -- also required for this formulation
这个公式的希望是
city_id
) 在较小的 BTree(该索引)上完成,因此更有可能驻留在 RAM 中,从而避免 I/O。步骤:
MEMORY
临时表。JOIN
返回原始表仅 1000 次。 (巨大的胜利。)(这里我可能是错的;它可能是 3210,但这仍然比 5555 好。)关于mysql - 如何正确预热 MySQL FULLTEXT 索引?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35952239/
MySQL 文档给出了创建全文索引的格式: | {FULLTEXT|SPATIAL} [INDEX|KEY] [index_name] (index_col_name,...) [index_opti
我有一个搜索程序,它必须在五个表中搜索相同的字符串。我想知道哪个在读取性能方面更好? 要将所有表合并到一个表中,然后在其上添加全文索引 在所有这些表中创建全文索引并对所有表发出查询,然后合并结果 最佳
现在在 vBulletin board 上工作,它运行在带有 InnoDB 表引擎的 MySQL 5.6.21 上。 vBulletin 中有一个默认的查询,它在一列上使用索引提示,同时在另外两列上使
假设我们在文本中有“ABCD1234EF”这个词。现在要找到它,我必须匹配确切的词。目标是通过“ABCD1234EF”、“ABCD”、“1234”或“EF”字符串找到它。不是“CD12”或类似的东西。
我想运行 FULLTEXT 搜索并仅返回具有不同(唯一)product_name 的结果,但 DISTINCT(product_name) 似乎不适用。任何正确方向的帮助或指示都会受到极大的欢迎。 M
我向表中添加了一个 FULLTEXT 索引,如下所示: ALTER TABLE TEST ADD FULLTEXT(name, descrip, notes); TEST 表有 100 行。我用一行中
我在网站的搜索栏中使用全文。代码如下所示, 搜索.php ".$name.": ".$desc.""; } ?> 这在大多数情况下都可以正常工作。在我的数据库中,描述列下的一行显示:“1. 切
我有一个标准的 MySQL 全文查询,如下所示: 从帐户中选择 * WHERE MATCH(first_name, username) AGAINST ('stringhere') 问题是,它无法找到
我正在尝试修改这篇文章中的完整路径检索代码: http://mikehillyer.com/articles/managing-hierarchical-data-in-mysql/在嵌套集模型中使用
我有一些列的全文,例如: car normal | car super | car extra 然后是类似的值 car normal | car super | car extra normal ca
我在 MySQL 全文 搜索中遇到区分大小写的问题。 我刚刚按照 MySQL doco http://dev.mysql.com/doc/refman/5.1/en/fulltext-boolean.
我必须匹配许多字段中的文本。目前我在查询中使用了Like。但是Like给出了太多结果。我已经阅读了有关mysql FULLTEXT查询的内容,并且尝试在我的查询中应用。但我不知道它是否有效。 旧查询:
我有一个名为 keywords 的字段存储的信息是用 | 分隔的关键字 例如: sky|Banana is good|apple|apple is red|sky is blue|green 我尝试做
我有一个标准的 MySQL 全文查询,如下所示: SELECT * FROM accounts WHERE MATCH(first_name, username) AGAINST ('stringhe
我正在尝试使用 mysql FULLTEXT 进行查询,但不幸的是它返回空结果,即使表包含那些输入关键字。 表:user_skills: +----+-------------------------
如果我搜索一个词“will walk”,那么结果将显示与搜索词相似的所有条目。例如: Search Term: will walkRecords: 1. It will walk.2. tomorro
我尝试运行以下查询 SELECT * FROM complains WHERE match(title, description) against('+lorem' IN BOOLEAN MODE)
发布这个,这样我也许可以从几个小时的搜索中拯救一些其他可怜的笨蛋,或者更好的是,从 MySQL 领域比我更聪明的人那里得到更好的答案。 ;-) 当使用 FULLTEXT 索引搜索 MySQL 时,如何
我有办法获得全文搜索背后的逻辑 示例表 +----+-------------+ | id | title | +----+-------------+ | 1 | Hello Worl
下面的查询需要 1.1s 来执行,EXPLAIN 显示了 FULLTEXT 索引的使用: SELECT SQL_NO_CACHE COUNT(*) FROM e_entity WHERE meta_o
我是一名优秀的程序员,十分优秀!