当前位置: 首页 > 面试题库 >

使用分页处理大量数据库条目会随着时间的推移而变慢

纪俊良
2023-03-14
问题内容

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

select blobCol from large_table 
where name= 'someKey' and city= 'otherKey' 
order by name
LIMIT <pageNumber*pageSize>, <pageSize>

对于大约50万条记录,这完全可以正常工作。我正在使用的页面大小为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内存,2个四核proc)具有以下条目

  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倍。

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

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

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

SELECT name
FROM my_table
where id = <anyId> // I use the id column for partitioning so I need this here
order by name
limit <pageSize * pageNumber>, 1

正弦页码以前未知,从值0开始,一直递增,直到查询返回null。您也可以执行选择计数(*),但它本身可能会花费很长时间,并且无助于优化任何内容。页数超过〜60后,每个查询大约需要2秒钟才能运行。

对我而言,页面大小为5000,因此我在位置0、5001、10001、15001等处获得了“名称”字符串列表。原来的页面数为1000,并在内存中存储1000个结果列表并不昂贵。

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

SELECT blobCol
FROM my_table
where name >= <pageHeader>
and name < <nextPageHeader>
and city="<any string>"
and id= 1

这将运行N次,其中N =先前获得的列表大小。由于“名称”是主键列,并且“城市”也已建立索引,因此EXPLAIN显示此计算是使用索引在内存中执行的。

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

如果有人有更好的解决方案,或者该解决方案存在明显错误,请告诉我



 类似资料:
  • 我在我的Flink应用程序(版本1.11.1)中使用事件时语义,该应用程序运行在AWS-kinesis analytics中。此应用程序的源为kinesis stream,汇为Postgres。notifyCheckpointComplete()上触发DB接收器时,检查点间隔为10秒。我正在使用多个协处理函数和ValueState连接不同的流,然后再将其放入Postgres。 观察到,检查点数据大

  • 我有一个正在运行的Spark Streaming应用程序,它使用mapWithState函数来跟踪RDD的状态。该应用程序可以正常运行几分钟,但随后会崩溃 我观察到,Spark应用程序的内存使用量随着时间的推移呈线性增加,尽管我已经为mapWithStateRDD设置了超时。请参阅下面的代码片段和内存使用情况- 如果每个RDD都有一个显式超时,为什么内存会随着时间线性增加? 我已经尝试增加内存,但

  • 我有一个模态组件,当不同的组件突变字段时,我被触发。我有一个getter在我的Vuex商店叫。模态被从称为的本地数据栏中驱动出来,我已经将其设置为getter。我正在检查的值,并且在我触发modal之后它是,但是数据仍然是false。我到底做错了什么?

  • 出于某种原因,我为Checkbutton变量编写的代码在函数内部时不会改变其工作方式,但是在函数外部和在其自身脚本中时,它会工作。下面是函数外部的代码 下面是在函数内部定义的代码 对于代码的顶部,当我选中一个框时,变量变为True。对于最下面的一个,不管我做什么,它们都保持在False。

  • 问题内容: 在我的代码中,用户可以上传一个excel文档,希望其中包含电话联系人列表。作为开发人员,我应阅读excel文件,将其转换为dataTable并将其插入数据库。问题是某些客户拥有大量的联系人,例如说5000个和更多的联系人,而当我尝试将这种数据量插入数据库时​​,它崩溃了,并给了我一个超时异常。避免这种异常的最佳方法是什么?它们的任何代码都可以减少insert语句的时间,从而使用户不必等

  • 我对JavaFX有问题。当我调整窗口大小时,它会自动调整锚具的大小以适应。此外,帆布的宽度和高度属性也被绑定到锚烷上。因此,如果通过重新调整窗口本身,锚烷变大,画布也会变大。 但是当我把窗户变小,宽度和高度保持不变时,问题就来了。我真的不明白那里的行为。 因此,如果在使窗户更大的宽度和高度是100。然后在把窗口缩小后,它仍然是100。。。除息的 这是我的画布控制器。 以及我对应的FXML: