我需要在Mysql表中保存大约78亿条记录。表是读写密集型的。我必须保持每小时插入率至少0.02亿条记录。虽然在桌面上搜索不应超过10秒。 我们有一个UI,用户可以根据不同的colums属性进行搜索。
大多数搜索查询可以是:
select * from mytable where prop1='sip:+100008521149' and
prop2='asdsa'
order by event_timestamp desc limit 10;
select * from mytable where prop1='sip:+100008521149'
order by event_timestamp desc limit 10;
select * from mytable where prop2='asdsa'
order by event_timestamp desc limit 10;
目前桌上有2个索引:
1- idx_1(prop1,event_timestamp)
2- idx_2(prop2,event_timestamp)
InnoDB设置如下:
innodb_buffer_pool_size = 70G
innodb_log_file_size = 4G
innodb_io_capacity=2000
innodb_io_capacity_max=6000
innodb_lru_scan_depth=2000
innodb_flush_log_at_trx_commit=2
innodb_log_buffer_size=16M
innodb_thread_concurrency = 0
innodb_read_io_threads = 64
innodb_write_io_threads = 64
innodb_autoinc_lock_mode = 2
bulk_insert_buffer_size=33554432
query_cache_type=1
query_cache_size=64M
innodb_flush_neighbors=0
expire_logs_days=10
max-connections=500
long_query_time = 5
read_buffer_size=16M
sort_buffer_size=16M
read_rnd_buffer_size=16M
innodb_doublewrite = 0
innodb_flush_method=O_DIRECT
Machine's RAM size is 99 GB.
一旦启动系统很快,但当记录达到2.2亿时,性能会下降很多。虽然我们使用的是LOAD INFILE,但插入速度非常慢。搜索索引参数时搜索速度非常快。看起来缓冲池是不够的。
我几乎没有问题:
使用此配置是否可以支持此类数据。
理想和实用的缓冲池大小应该是7 亿条记录。
UPADTE:1
Q-表比RAM大得多,对吗?无法使buffer_pool足够大 - 它必须小于ram,否则性能会受损。
A-RAM大小为100 GB,缓冲池为70 G。是的,数据大小太大而不是RAM。
Q-请提供SHOW CREATE TABLE;我需要调查几个问题。 (数据类型,字段大小等)
A-所有字段都是字符串类型。我们已经使用了varchar(127)。 PK是自动生成id bigint(20)。
问题 - LOAD DATA INFILE中有多少条记录?你直接加入桌子吗? LOAD多久一次?
每个文件A- 100000条记录。多个线程正在将数据从CSV文件加载到DB。在最初的迁移中,我们必须不断加载它直到达到6.5亿条记录。之后频率将降低到每15分钟左右。
Q- Master + Slave:请记住,所有写操作都是在Slave上执行的。如果你有大量的读取,那么不止一个Slave会将读数分散开来,从而得到一些扩展。
A- 我们目前正在使用MASTER / SLAVE方法进行测试。
我们用MYISAM制作了MASTER而没有索引。 MASTER将用于插入。 拥有INNODB和2个索引的SLAVE。搜索将在其上执行。 两者都是不同的机器,不共享RAM或CPU。 该应用程序位于第三台机器上。
问:你有旋转驱动器吗?还是SSD? A-如何检查?问:你的行似乎很大。是TEXT还是BLOB?如果是这样,SELECT *可能是一个严重的性能负担。
A-是行有50列,但数据大约在15-20列。我们无法减小数据类型的大小,因为所有字段都可以容纳任意数量的字母数字数据。所有这些都是TEXTS no BLOBS。
答案 0 :(得分:4)
关闭查询缓存:每次INSERT
发生时,它必须清除质量控制中的所有条目 - 每秒5555次!
query_cache_type = 0
query_cache_size = 0
第一个查询需要INDEX(prop1, prop2, event_timestamp)
。 (prop1和prop2可以交换。)
使用该添加的索引,三个查询中的每一个将在索引中触摸不超过10行,并且对数据进行不超过10次随机(?)提取。在最坏的情况下,这只是大约11次磁盘命中。而@ Bernd的懒惰评论'不会让它变得更好。
表比RAM大得多,对吗? buffer_pool不能足够大 - 它必须小于ram,否则性能会受到。
请提供SHOW CREATE TABLE
;我需要调查几个问题。 (数据类型,字段大小等)
LOAD DATA INFILE
中有多少条记录?你LOAD
直接进入桌子吗?常见的是LOAD
?
Master + Slave:请记住,所有写操作都是在Slave上执行的。如果你有很多读取,那么不止一个Slave会传播读取,从而得到一些扩展。
你有旋转驱动器吗?还是SSD?
你的行似乎很大。有TEXTs
还是BLOBs
?如果是这样,SELECT *
可能是一个严重的性能负担。
答案 1 :(得分:3)
我通过将MYSQL DB替换为Elasticsearch来实现此要求。它看起来非常适合快速插入速率和快速搜索。此外,Lucene的全文功能使其成为一个完美的工具。 ES的最佳部分是硬件要求非常低。它水平缩放而不是垂直缩放。
答案 2 :(得分:2)
这不是答案,但我不能在评论中格式化
你可以试试这个,看看它是否更快。所以MySQL不能只对id(主键)
的孔行进行排序SELECT r.*
FROM (
SELECT id
FROM mytable
WHERE
prop1='sip:+100008521149'
AND
prop2='asdsa'
ORDER BY event_timestamp DESC
LIMIT 10
) AS r
LEFT JOIN mytable m ON m.id =r.id
ORDER BY r.event_timestamp DESC;