内置的数据无法实现高性能

这里说的“内”, 是指数据库之内。

当数据量变大时,我们常常会感到数据库的性能下降明显,但是,无论怎样优化 SQL(存储过程)都仍然与根据数据量和运算复杂度计算出来的理论性能相差甚远。这主要由如下几方面原因造成:

1. SQL 限制与优化困难

我们已经多次说过,由于关系代数和 SQL 语法的限制,有许多高效的算法无法实施,比如前面说过的遍历复用技术,以及去年谈过的 JOIN 优化方法。使用 SQL 实现这类运算时,只能采用复杂度更高的方法,冗余的数据访问量和计算量非常大,而且也很难利用多 CPU 进行并行计算。

SQL 不提倡分步计算,经常一条语句写出几百行、嵌套很多层。不分步的长语句很难利用某个子句的计算结果,常常带来不必要的重复计算。而且过于复杂的也会给数据库优化引擎造成负担,优化引擎不能很好地理解运算逻辑而设计出最优的执行路径。我们常常发现一条语句的几个子部分执行都很快,结果集也不大,但合起来写到一句 SQL 中就会很慢。

2. 存储过程性能差

对于复杂的多步骤计算,我们常常要编写存储过程才能实现。而和 SQL 相比,存储过程的取数遍历过程要慢得多。同一个表的数据,使用存储过程先 FETCH 出来再做聚合,要比直接用 SQL 聚合的性能慢出几倍到十几倍,本来这两者的运算性能应当是差不多的(计算复杂度与数据访问量都一样)。有些针对明细数据的复杂处理只能把数据一条条取出才能实现时,这个性能就没办法得到保证了。

在存储过程中,为了利用前面计算出来的中间结果,只要涉及集合性数据一般都要使用临时表。而建表写数的动作也是非常慢的,数据库有太多约束性要求,而且常常需要把临时表落地到外存。

3. 直接外部计算不现实

如果我们不采用 SQL,而将数据读出后在库外计算,是否可以提高性能呢?

大多数情况仍然不可以。一方面原因是数据库 IO 性能大都很差,从数据库中取数,要比从文件系统中读数的性能差出一个数据量,经常发生取数时间远远超过计算时间的现象。

而且,有些高效算法会要求有特殊的存储格式,比如需要事先将数据排序存储,从而可以采用分段定位查找或实现有序归并算法,而基于无序集合的 SQL 在理论上就无法支持,必须先排序才能保证取出数据的有序性,结果排序时间会超过计算本身。再比如行存或列存的选择,一般数据库只会采用一种(支持 OLTP 用行存且不压缩,面向 OLAP 用列存并压缩),但使用行存还是列存需要由计算目标决定,在遍历式计算采用列存较为合适,而使用索引定位查找时则更适合用行存。有时为了性能还可能把同一份数据存储冗余的多份以面向不同用途,而在数据库中很难有这么灵活的处理方式。


解决办法,就是数据外置,具体说就是把数据搬出数据库。使用合理的存储方案再配以适用的算法,对于许多几百上千行的存储过程,经过这样的改造后,性能常常都有几倍的增长。

当然,这又会带来新的问题。主要有三个方面:一是可管理性,在数据库中有统一的数据视图和约束性检查,而外部文件系统则没有这些东西;二是安全性,数据库是个封闭体系,获取数据的接口很单一,总有帐号认证的过程,而文件系统也没有这些东西;三是数据更新能力,数据在不断地变化中,数据库有完整的数据更新功能,文件系统这方面却很弱,一般只能做追加,还很难保证追加过程中的一致性(中途出错时恢复)。

目前阶段这个事还是需要权衡,获得了数据库的方便性就得不到高性能,要数据外置的高性能就要牺牲方便性。不过,随着技术的进步,在文件系统上加强可管理性、安全性以及可更新能力又不牺牲或很少牺牲其性能,还是有可能做到的,数据库的封闭性总要被打破。

join 高性能_内置的数据无法实现高性能相关推荐

  1. 数据蒋堂 | 内置的数据无法实现高性能

    作者:蒋步星 来源:数据蒋堂 本文共1400字,建议阅读7分钟. 获得了数据库的方便性就得不到高性能,要数据外置的高性能就要牺牲方便性. 这里说的"内", 是指数据库之内. 当数据 ...

  2. 内置的数据无法实现高性能

    这里说的"内", 是指数据库之内. 当数据量变大时,我们常常会感到数据库的性能下降明显,但是,无论怎样优化 SQL(存储过程)都仍然与根据数据量和运算复杂度计算出来的理论性能相差甚 ...

  3. python内置作用域_python内置金融数据Python 五点搞定作用域

    1.块级作用域 想想此时运行下面的程序会有输出吗?执行会成功吗?#块级作用域 if 1 == 1: name = "lzl" print(name) for i in range( ...

  4. java分页插件PageHelper的内置list数据操作失败

    问题描述: java分页插件PageHelper的内置list数据在hanlder处理器中获取失败,但是测试确通过了,如下图 但是测试代码成功 @ContextConfiguration(locati ...

  5. java使用poi在word中生成柱状图、折线图、饼图、柱状图+折线图组合图、动态表格、文本替换、图片替换、更新内置Excel数据、更新插入的文本框内容、合并表格单元格;

    本文参考地址:https://blog.csdn.net/wangxiaoyingWXY/article/details/95377533 在参考文章的基础上,增加了扩展.感谢被参考的妹子.另外该博客 ...

  6. js 序列化内置对象_内置序列化技术

    js 序列化内置对象 本文是我们名为" 高级Java "的学院课程的一部分. 本课程旨在帮助您最有效地使用Java. 它讨论了高级主题,包括对象创建,并发,序列化,反射等. 它将指 ...

  7. 内置对象和内置函数_内置假对象

    内置对象和内置函数 尽管模拟对象是进行单元测试的理想工具,但通过模拟框架进行模拟可能会将您的单元测试变成难以维护的混乱. 这种复杂性的根本原因是我们的对象太大. 他们有很多方法,这些方法返回其他对象, ...

  8. 表单_内置Filed

    Django表单 前面介绍了Django中form表单的重要作用有:     1.生成页面可执行的HTML标签     2.对应户的数据进行校验     3.保留上次输入的内容 注: 1.在实际开发中 ...

  9. python-DRF_限流Throttling_自定义频率类_内置频率类使用_过滤排序功能

    DRF-Django rest framework 认证权限频率 1. 限流Throttling 可以对接口访问的频次进行限制,以减轻服务器压力 一般用于付费购买次数,投票等场景使用 1. 自定义频率 ...

最新文章

  1. apache+tomcat 搭建负载均衡系统
  2. JavaScript定时器的工作原理(翻译)
  3. 用PHP实现var_export
  4. WP7 开发(二) 通过Geometries来绘制形状
  5. 采样算法哪家强?一个针对主流采样算法的比较
  6. 水晶报表自定义函数(替换并截取特殊字符后内容)
  7. java redirect 超时_java – Spring Security 3.0重定向到超时的页面
  8. silverlight寻奇
  9. Linux集群和自动化维1.1.1 什么是HTTP 1.1
  10. leetcode 171. Excel Sheet Column Number
  11. 前后端分离实现文件下载功能
  12. 电阻阻值标准以及选择参照表
  13. java udp转发_JAVA NIO udp 实现 群转发
  14. 微波遥感几个重要公式
  15. 探索变量之间的关系(python3)
  16. 根据三个点的坐标计算三角形面积
  17. 网线连接网络有黄色感叹号
  18. 数码摄影入门:焦距是什么?
  19. 完整简洁的Oracle获得汉字字符串拼音首字母和全拼的函数
  20. 微信QQ的二维码登录原理浅析

热门文章

  1. SpringSecurity - 基础篇
  2. SpringBatch 自定义ItemReader和可重新启动Reader(十五)
  3. linux deepin/debian/ubuntu apt查看软件版本 apt安装指定版本的包
  4. spring boot使用外置tomcat部署需增加如下初始化类
  5. Java计算两点间经纬度距离(两种方式)
  6. 支付宝开发中return_url和notify_url的区别分析
  7. 线程池Executors创建多线程案例
  8. 不小心关闭了explorer.exe进程,桌面变白解决办法
  9. id3与软件测试,ID3算法的实现
  10. python实现日历功能_Python实现的简单万年历例子分享