我正在运行一个PHP脚本,该脚本使用包含数百万行的表搜索相对较大的MySQL实例,以在列description
中找到类似“糖尿病”的术语,该列具有全文索引。但是,有一天我只通过几百个查询,所以看起来我的方法永远不会起作用。 description
列中的条目平均长度为1000个字符。
我正在试图找出我的下一步行动,我有几个问题:
我的MySQL表中有不必要的列,没有被查询。会删除那些会影响性能吗?
我假设在本地运行而不是在RDS上运行会大大提高性能吗?我有一个不错的macbook,但我选择了RDS,因为成本不是问题,我试图在比我的Macbook更好的实例上运行。
使用像Go而不是PHP这样的编译语言会比测试示例中的5-10x提升人报告更多吗?也就是说,鉴于我的任务是否有理由认为静态语言会产生100倍或更高的速度提升?
我应该将数据放在文本或CSV文件而不是MySQL中吗?使用MySQL只会造成不必要的开销吗?
这是查询:
SELECT id
FROM text_table
WHERE match(description) against("+diabetes +mellitus" IN BOOLEAN MODE);
这是查询的EXPLAIN输出行,显示优化器正在使用FULLTEXT索引:
1 SIMPLE text_table fulltext idx idx 0 NULL 1 Using where
RDS实例是 db.m4.10xlarge ,它有160GB的RAM。 InnoDB缓冲池通常约占RDS实例RAM的75%,这使其达到120GB。
text_table状态为:
Name: text_table
Engine: InnoDB
Version: 10
Row_format: Compact
Rows: 26000630
Avg_row_length: 2118
Data_length: 55079485440
Max_data_length: 0
Index_length: 247808
Data_free: 6291456
Auto_increment: 29328568
Create_time: 2018-01-12 00:49:44
Update_time: NULL
Check_time: NULL
Collation: utf8_general_ci
Checksum: NULL
Create_options:
Comment:
这表明该表有大约2600万行,数据和索引的大小为51.3GB,但这不包括FT索引。
对于FT索引的大小,请查询:
SELECT stat_value * @@innodb_page_size
FROM mysql.innodb_index_stats
WHERE table_name='text_table'
AND index_name = 'FTS_DOC_ID_INDEX'
AND stat_name='size'
FT索引的大小为480247808
。
答案 0 :(得分:2)
跟进上面关于并发查询的评论。
如果查询需要30秒才能执行,那么您用于客户端应用程序的编程语言就不会有任何区别。
我有点怀疑查询实际需要1到30秒才能执行。我测试了MySQL全文搜索,我发现即使在我的笔记本电脑上也能在1秒内完成搜索。请参阅我的演示文稿https://www.slideshare.net/billkarwin/practical-full-text-search-with-my-sql
这可能不是查询花了这么长时间,但它是您提交的提交查询的代码。你的代码还在做什么?
您如何衡量查询效果?你在使用MySQL的查询分析器吗?请参阅https://dev.mysql.com/doc/refman/5.7/en/show-profile.html这将有助于隔离MySQL执行查询所需的时间,因此您可以比较其余PHP代码运行所需的时间。
使用PHP将是单线程的,因此您一次串行运行一个查询。您使用的RDS实例有40个CPU内核,因此您应该能够一次执行多个并发查询。但每个查询都需要由自己的客户端运行。
因此,一个想法是将输入搜索项分成至少40个子集,并针对每个相应的子集运行PHP搜索代码。 MySQL应该能够很好地运行并发查询。也许会有轻微的开销,但这将通过并行执行得到补偿。
您可以手动将搜索词拆分为单独的文件,然后以每个相应的文件作为输入运行PHP脚本。这将是解决这个问题的直接方法。
但要真正专业,请学会使用像GNU parallel这样的工具来运行40个并发进程,并自动将这些进程分开。