处理大量具有分页的数据库条目随着时间的推移而减慢

我正在尝试从我的表中处理数百万条记录(大小约为30 GB),我目前正在使用分页(mysql 5.1.36)。 我在for循环中使用的查询是

select blobCol from large_table where name= 'someKey' and city= 'otherKey' order by name LIMIT ,  

这适用于大约500K记录。 我使用的页面大小为5000,在第100页之后,查询开始显着减慢。 第一个~80页是在2-3秒内提取的,但在第130页后,每个页面大约需要30秒才能检索,至少要到第200页。我的一个查询大约有900页,这需要很长时间。

 The table structure is (type is MyISAM) name char(11) id int // col1 & col2 is a composite key city varchar(80) // indexed blobCol longblob 

我该怎么做才能加快速度? 查询的解释显示了这一点

 select_type: SIMPLE possible_keys: city key : city type: ref key_len: 242 ref: const rows: 4293720 Extra: using where; using filesort 

万一它有帮助,我的服务器my.cnf(24 GB RAM,2四核处理)有这些条目

  key_buffer_size = 6144M max_connections = 20 max_allowed_packet = 32M table_open_cache = 1024 sort_buffer_size = 256M read_buffer_size = 128M read_rnd_buffer_size = 512M myisam_sort_buffer_size = 128M thread_cache_size = 16 tmp_table_size = 128M max_heap_table_size = 64M 

这就是我所做的,并将总执行时间减少了10倍。

我从原始查询的执行计划中意识到,它是使用filesort对所有结果进行排序并忽略索引。 这有点浪费。

我的测试数据库:5 M记录,20 GB大小。 表格结构与问题相同

我没有直接在第一个查询中获取blobCol,而是首先获得每个页面开头的“name”值。 无限期运行此查询,直到返回0结果。 每次都将结果添加到列表中

 SELECT name FROM my_table where id =  // I use the id column for partitioning so I need this here order by name limit , 1 

先前页面编号以前不知道,从值0开始并继续递增,直到查询返回null。 您也可以执行选择计数(*),但这本身可能需要很长时间,并且无法帮助优化任何内容。 一旦页码超过~60,每个查询大约需要2秒钟。

对我来说,页面大小是5000,所以我得到了位置0,5001,10001,15001等的“名称”字符串列表。 结果为1000的页数并将1000个结果的列表存储在内存中并不昂贵。

现在,遍历列表并运行此查询

 SELECT blobCol FROM my_table where name >=  and name <  and city="" and id= 1 

这将运行N次,其中N =先前获得的列表的大小。 由于’name’是主键col,’city’也被索引,因此EXPLAIN显示此计算是使用索引在内存中执行的。

现在,每个查询需要1秒才能运行,而不是原来的30-40。 因此,结合每页2秒的预处理时间,每页的总时间为3-4秒而不是30-40。

如果有人有更好的解决方案,或者这个问题有明显的错误,请告诉我

您可以使查询更精确,因此限制更低。

 SELECT col1,col2, col4 FROM large_table WHERE col1>"SomeKey" OR (col1="SomeKey" AND col2>="OtherKey") ORDER BY col1,col2 LIMIT PageSize 

但在每次数据库调用后更新“SomeKey”和“OtherKey”。

我过去曾尝试使用Oracle 10g数据库并获得相同的结果(我的表有6000万行)。 第一页被快速检索,但随着页码数量的增加,查询速度太慢。 由于它们看起来正确并且我不确定通过调整数据库配置可以实现什么,因此您无法对索引进行任何操作。 我想我有不同的要求,但我发现的唯一解决方案是将数据转储到文件中。 如果col1的值集合有限,则可以删除col1并生成n个表,每个表对应col1的每个已知值。 如果col1未知,那么我不知道解决方案。 您可以从非常大的表中检索小数据集,但检索大量数据需要花费大量时间,而分页对您完全没有帮助。 您必须通过转储到文件或生成其他表来分区数据进行预处理。