IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 大数据 -> 从数据库读取大量数据的方式对比 -> 正文阅读

[大数据]从数据库读取大量数据的方式对比

数据库读取大量数据方式

当从数据库里读大量的数据时,容易导致连接异常或者程序内存崩溃。
下文将对比"直接读取",“分页读取”,"游标读取"等方式的性能和操作方式。
游标读取可以参照:python中数据库游标的使用总结

性能比较

编程语言:python

使用的库: psycopg2

数据库:postgresql

数据量: 接近900w条

直接全部读取:

语句:

select * from xxxx 

代码:

 with psycopg2_conn.cursor() as cursor:  # 获取数据库连接的对象
            first_time = time.time()
            sql_script = sql_script.strip(" ").strip(";")
            print(u'执行查询前的内存使用:%.4f GB' % (psutil.Process(os.getpid()).memory_info().rss / 1024 / 1024 / 1024))
            cursor.execute(sql_script)
            rows = cursor.fetchall()
            print("总的查询耗时: {:.6f}秒".format(time.time() - first_time),
                  '查询后内存使用:%.4f GB' % (psutil.Process(os.getpid()).memory_info().rss / 1024 / 1024 / 1024))

可以看到查询所消耗的时间和程序占用的内存爆炸,内存使用超过10G,耗时也来到了80s。
在这里插入图片描述

分页读取:

语句:

select * from xxxx  limit {count} OFFSET {page * count}

代码:

        with psycopg2_conn.cursor() as cursor:  # 获取数据库连接的对象
            first_time = time.time()
            sql_script = sql_script.strip(" ").strip(";")
            print(u'执行查询前的内存使用:%.4f GB' % (
                psutil.Process(os.getpid()).memory_info().rss / 1024 / 1024 / 1024))
            while True:
                start_time = time.time()
                current_sql_script = f"{sql_script} limit {count} OFFSET {page * count}"
                cursor.execute(current_sql_script)
                rows = cursor.fetchall()
                print( f'limit:{count},OFFSET:{page * count}',
                       "本次查询耗时: {:.6f}秒".format(time.time() - start_time),
                       "总的查询耗时: {:.6f}秒".format(time.time() - first_time),
                       '目前内存使用:%.4f GB' % (psutil.Process(os.getpid()).memory_info().rss / 1024 / 1024 / 1024))
                if len(rows) == count:
                    page += 1
                    continue
                else:
                    break

一开始的情况:

在这里插入图片描述

查询至500w数据时:可以观察到单次查询的耗时明显上升,但内存使用情况正常
在这里插入图片描述

查询至最后的数据时,单次查询耗时已经超过1秒,总耗时也已经达到532秒。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SVxapd3n-1661851208514)(/Users/linglingfa/Library/Application Support/typora-user-images/image-20220830161640141.png)]

原因:当查询500w处的后1w条数据时,数据库会先查出501w的数据,然后丢掉500w,返回剩下的1w条数据。这里优化可以考虑利用索引or条件,具体可以谷歌搜下优化方式。

使用游标读取:

代码:

def test_database_time(self):
    with psycopg2_conn.cursor(name='my_test_cursor') as cursor:  # 获取数据库连接的对象
        first_time = time.time()
        sql_script = sql_script.strip(" ").strip(";")
        print(u'执行查询前的内存使用:%.4f GB' % (psutil.Process(os.getpid()).memory_info().rss / 1024 / 1024 / 1024))
        cursor.execute(sql_script)
        rows = cursor.fetchmany(10000)
        count = len(rows)
        while len(rows) == 10000:
            start_time = time.time()
            rows = cursor.fetchmany(10000)
            count += len(rows)
            print( f'获取总数:{count}',
                   "本次查询耗时: {:.6f}秒".format(time.time() - start_time),
                   "总的查询耗时: {:.6f}秒".format(time.time() - first_time),
                   '目前内存使用:%.4f GB' % (psutil.Process(os.getpid()).memory_info().rss / 1024 / 1024 / 1024))

一开始情况:

在这里插入图片描述

查询至500w数据时:单次查询耗时无明显变化

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KuD8tEtG-1661851208514)(/Users/linglingfa/Library/Application Support/typora-user-images/image-20220830163552572.png)]

查询至最后数据时,单次查询耗时依旧保持稳定,总的耗时略微超过“直接全部读取的方式”

在这里插入图片描述

大致原理:这里数据库会保留一个类似于游标的东西,当查询500w处的后1w条数据时,游标正处于500w处,可以直接获取到接下来的1w条数据,所以单次查询耗时依旧很快。这种也是有对应的缺点的,可能会影响数据库本身的内存以及其他查询链接。 这里具体的实现方式得看数据库的类型以及我们编程语言中的操作方式,网上众说纷纭,这里只做大致原理的解析。

  大数据 最新文章
实现Kafka至少消费一次
亚马逊云科技:还在苦于ETL?Zero ETL的时代
初探MapReduce
【SpringBoot框架篇】32.基于注解+redis实现
Elasticsearch:如何减少 Elasticsearch 集
Go redis操作
Redis面试题
专题五 Redis高并发场景
基于GBase8s和Calcite的多数据源查询
Redis——底层数据结构原理
上一篇文章      下一篇文章      查看所有文章
加:2022-09-04 01:18:22  更:2022-09-04 01:19:43 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 10:41:10-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码