首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往
  • 您找到你想要的搜索结果了吗?
    是的
    没有找到

    爬虫数据存储技术比较:数据库 vs. 文件 vs. NoSQL

    事件描述: 在进行网络爬虫开发时,数据存储是一个关键的环节。不同的数据存储技术有着各自的特点和适用场景。本文将比较常用的数据库、文件和NoSQL三种数据存储技术,以帮助开发者选择合适的存储方式。 亮点介绍: 1.数据库:提供结构化数据存储和能查询的效高力。 2.文件:简单易用,适合小规模数据存储和快速读写。 3.NoSQL:灵活的数据模型和可扩展性,适用于大规模数据存储和分布式系统。 背景介绍: 数据库是一种常见的数据存储方式,如MySQL、PostgreSQL等,它们提供了结构化数据存储和强大的查询能文件。力存储是一种简单的存储方式如,CSV、JSON等,适用于小规模数据存储和快速读写。NoSQL是一类非关系型数据库,如MongoDB、Redis等,它们具有灵活的数据模型和可扩展性。 示例代码: 下面是Python的pymysql库的实现参考

    03

    事务处理的数据存储

    在上篇文章我们讨论了数据模型,今天试着讨论更基础的数据存储和搜索。数据存储根据开发者使用,可以分为一般的事务处理和数据分析,因为这两者面临的情况不一样。事务处理聚焦于快速的存储和搜索少量的数据,但是数据分析需要读取大量的数据去进行聚合,而不怎么考虑读取花费的时间。后者一般称为数据仓库。 首先我们先看看传统数据库和大部分NoSQL的数据存储引擎。这个实际上分为两个流派,一个是基于日志结构,主要使用了LSM树,另一个是基于OS的页的结构,就是所谓的B树。这么说可能比较难懂。让我们想象一下,假设你有一个excel,里面存储了一条数据a,b,如果我们想查询a,我们可以遍历excel找到满足以a开头的数据a,b。这就是一个简单的数据库,存储数据时,只要简单的添加在下一列。查找时进行遍历,找到符合条件的。让我们想想这会有什么问题。对于数据存储,我们只需要简单的添加数据,对于磁盘这样极有效率,当然实际上的数据库还要考虑并行处理、磁盘存储空间不足等等情况。存储数据的file,就是所谓的log。另一方面,对于搜索数据,这个效率就相当慢了,因为每次搜索数据都需要遍历整个文件,时间复杂度是线性的增长,这时候我们就需要索引了。显然索引对于整个数据存储文件而言,是额外的存储结构,维护索引结构会牺牲write的效率。 对于索引结构,首先想到的是key-value结构。例如对于数据a,b c,f,d这种数据,我们可以用一个索引a,0 b,3这种hash map的形式0和3代表着文件的offset,我们查找数据的时候,先去hash map找到对应的key值,获得offset,我们就能获得key值对应的value。这听起来很简单,然而这就是Bitcask的实现方式。这个索引结构是完全存储在内存当中,如果超出内存的话,就会放在磁盘上。如果数据一直在增长,磁盘空间肯定会有不足的那一刻,解决办法就是将数据拆分为固定大小的segment,以及在合适的时候,合并segment,根据时间戳,保留最新的value值,重新写入新的segment,对旧的进行删除。对于实际的工程,我们还需要考虑 1.文件存储的格式,一般而言应该是以bytes存储 2.删除数据时,应该加上一个标签,比如tombstone,在合并segment时,对数据进行删除 3.数据库崩溃重新恢复,Bitcask使用的是快照的方式在磁盘保存索引结构 4.并发的写入数据,这个需要检查点来处理数据写入时数据库崩溃 5.并发控制,因为文件的immutable,所以并发控制相当简单。 但是这个依然存在问题,让我们想想,那就是hash table必须存储在内存中,这个对于大数据时很不友好,即使你是存储在磁盘上。并且对于范围查找很不友好,因为你需要遍历所有key去查找一个范围内的一个key。 为了解决范围查找,人们又提出了在创建索引时,我们可以按照key值进行排序,这样的存储方式叫做SSTable。这样有下面的几个好处,合并segment变得更有效率了,因为你只需要读取开始的key和结束的key就可以了。在保存索引时,也不需要将所有的key存储在内存里,只需要保存每个segment的开始key和结束key。读取数据时,也不需要遍历所有的key值了。那么对于维护索引呢?我们在写入数据时,会先写入memtable(存储在内存的例如红黑树之类的数据结构)。当memtable超过某个阈值时,会将memtable写入到磁盘的segment中。在读取数据时,我们会首先在memtable中查找数据,然后再根据时间逐步读取segment。每隔一段时间,后台进程便会合并segment,清理垃圾数据。这样处理的唯一问题,就是memtable遇到服务器崩溃。我们可以牺牲一部分write的效率,生成一个独立的log去立马保存写入的数据,这个log的唯一用途就是防止memtable的丢失。 上面的就是现在HBase、LevelDB、Lucene这些使用的LSM树结构。对于其的优化,目前可以使用布隆过滤器、size-tiered等方式去优化读取和合并segment。除了LSM树,目前还有一个广泛使用的索引,那就是B树。 B树主要是利用了操作系统的页结构,将数据拆分成一个固定尺寸的block块,使用存储address和location,类似于指针的方式存储数据。具体细节不多说,网上的文章一大堆。我们需要考虑的是负载因子和二叉树的平衡。对于每次的写入和修改数据,我们都需要找到key值在系统里对应的address去修改数据,重新写入,同样为了防止数据崩溃,一般的数据库会使用预写日志(WAL)去保存每一次数据的修改和写入。 除了这些索引,还有所谓的二级索引。这个类似于倒排索引。不仅如此,还有基于列的存储方式,这个大多是为了数据仓库服务的。

    03

    SQL(及存储过程)跑得太慢怎么办?

    但遗憾的是,仍然有相当多情况无论怎样优化都不可能跑得更快。这里做 SQL 性能优化真是让人干瞪眼 介绍了一些,并做了相应的技术分析。由于其理论基础关系代数的局限,SQL缺乏离散性和有序集合等特性的支持使得SQL在表达某些高性能算法时异常困难,甚至完全写不出来,只能采用比较笨的低性能算法,眼睁睁地看着硬件资源被白白浪费。在 写着简单跑得又快的数据库语言 SPL 中有对SQL理论基础缺陷的通俗解释。也就是说,SQL的慢是理论性的,这种问题仅仅由数据库在工程层面优化只能局部改善(确实有不少商业数据库能够自动识别某些SQL并转换成高性能算法),而不能根本地解决问题(情况复杂时数据库优化引擎都会“晕”掉,只能按SQL的书写逻辑执行成低性能算法)。理论性的缺陷当然也不能寄希望于更换数据库而得到解决,只要还是用SQL,即使采用分布式数据库、内存数据库也还是这种情况,在消耗更大成本的资源后当然也能有一定的性能提升,但和硬件本应能够达到的性能仍然有巨大的差距。

    02

    一篇文章彻底明白Hive数据存储的各种模式

    Hive是基于Hadoop分布式文件系统的,它的数据存储在Hadoop分布式文件系统中。Hive本身是没有专门的数据存储格式,也没有为数据建立索引,只需要在创建表的时候告诉Hive数据中的列分隔符和行分隔符,Hive就可以解析数据。所以往Hive表里面导入数据只是简单的将数据移动到表所在的目录中   Hive的数据分为表数据和元数据,表数据是Hive中表格(table)具有的数据;而元数据是用来存储表的名字,表的列和分区及其属性,表的属性(是否为外部表等),表的数据所在目录等。下面分别来介绍。 一、Hive的数据存储   在让你真正明白什么是hive 博文中我们提到Hive是基于Hadoop分布式文件系统的,它的数据存储在Hadoop分布式文件系统中。Hive本身是没有专门的数据存储格式,也没有为数据建立索引,只需要在创建表的时候告诉Hive数据中的列分隔符和行分隔符,Hive就可以解析数据。所以往Hive表里面导入数据只是简单的将数据移动到表所在的目录中(如果数据是在HDFS上;但如果数据是在本地文件系统中,那么是将数据复制到表所在的目录中)。   Hive中主要包含以下几种数据模型:Table(表),External Table(外部表),Partition(分区),Bucket(桶)(本博客会专门写几篇博文来介绍分区和桶)。   1、表:Hive中的表和关系型数据库中的表在概念上很类似,每个表在HDFS中都有相应的目录用来存储表的数据,这个目录可以通过${HIVE_HOME}/conf/hive-site.xml配置文件中的 hive.metastore.warehouse.dir属性来配置,这个属性默认的值是/user/hive/warehouse(这个目录在 HDFS上),我们可以根据实际的情况来修改这个配置。如果我有一个表wyp,那么在HDFS中会创建/user/hive/warehouse/wyp 目录(这里假定hive.metastore.warehouse.dir配置为/user/hive/warehouse);wyp表所有的数据都存放在这个目录中。这个例外是外部表。   2、外部表:Hive中的外部表和表很类似,但是其数据不是放在自己表所属的目录中,而是存放到别处,这样的好处是如果你要删除这个外部表,该外部表所指向的数据是不会被删除的,它只会删除外部表对应的元数据;而如果你要删除表,该表对应的所有数据包括元数据都会被删除。   3、分区:在Hive中,表的每一个分区对应表下的相应目录,所有分区的数据都是存储在对应的目录中。比如wyp 表有dt和city两个分区,则对应dt=20131218,city=BJ对应表的目录为/user/hive/warehouse /dt=20131218/city=BJ,所有属于这个分区的数据都存放在这个目录中。   4、桶:对指定的列计算其hash,根据hash值切分数据,目的是为了并行,每一个桶对应一个文件(注意和分区的区别)。比如将wyp表id列分散至16个桶中,首先对id列的值计算hash,对应hash值为0和16的数据存储的HDFS目录为:/user /hive/warehouse/wyp/part-00000;而hash值为2的数据存储的HDFS 目录为:/user/hive/warehouse/wyp/part-00002。   来看下Hive数据抽象结构图

    04
    领券