当前位置:首页 » 服务存储 » 存储查询都快得数据结构
扩展阅读
webinf下怎么引入js 2023-08-31 21:54:13
堡垒机怎么打开web 2023-08-31 21:54:11

存储查询都快得数据结构

发布时间: 2022-09-19 18:08:54

⑴ 什么是key value 存储

key是关键字、value是值。

key-value分布式存储系统查询速度快、存放数据量大、支持高并发,非常适合通过主键进行查询,但不能进行复杂的条件查询。

Key-value数据库是一种以键值对存储数据的一种数据库,类似Java中的map。可以将整个数据库理解为一个大的map,每个键都会对应一个唯一的值

(1)存储查询都快得数据结构扩展阅读:

由于key-value的键值对特性,被广泛应用键值对数据库中,如redis、memchaced,查询速度快、存放数据量大、支持高并发,非常适合通过主键进行查询,但不能进行复杂的条件查询。

key-value型内存数据库还具有以下特性:

1、亚毫秒级延时。

2、语法简单,易用性强。

3、支持集群方式水平扩展。

4、支持哈希、列表、集合、有序集合等复杂的数据结构。有更多的应用场景

⑵ 常用数据结构有哪些

数据结构分为8类有:数组、栈、队列、链表、树、散列表、堆、图。数据结构是指相互之间存在着一种或多种关系的数据元素的集合和该集合中数据元素之间的关系组成 。

1、数组

数组是可以再内存中连续存储多个元素的结构,在内存中的分配也是连续的,数组中的元素通过数组下标进行访问,数组下标从0开始。例如下面这段代码就是将数组的第一个元素赋值为 1。

2、栈

栈是一种特殊的线性表,仅能在线性表的一端操作,栈顶允许操作,栈底不允许操作。 栈的特点是:先进后出,或者说是后进先出,从栈顶放入元素的操作叫入栈,取出元素叫出栈。

3、队列

队列与栈一样,也是一种线性表,不同的是,队列可以在一端添加元素,在另一端取出元素,也就是:先进先出。从一端放入元素的操作称为入队,取出元素为出队。

4、链表

链表是物理存储单元上非连续的、非顺序的存储结构,数据元素的逻辑顺序是通过链表的指针地址实现,每个元素包含两个结点,一个是存储元素的数据域 (内存空间),另一个是指向下一个结点地址的指针域。根据指针的指向,链表能形成不同的结构,例如单链表,双向链表,循环链表等。

5、树

树是一种数据结构,它是由n(n>=1)个有限节点组成一个具有层次关系的集合。把它叫做 “树” 是因为它看起来像一棵倒挂的树,也就是说它是根朝上,而叶朝下的。

6、散列表

散列表,也叫哈希表,是根据关键码和值 (key和value) 直接进行访问的数据结构,通过key和value来映射到集合中的一个位置,这样就可以很快找到集合中的对应元素。

7、堆

堆是一种比较特殊的数据结构,可以被看做一棵树的数组对象,具有以下的性质:堆中某个节点的值总是不大于或不小于其父节点的值;堆总是一棵完全二叉树。将根节点最大的堆叫做最大堆或大根堆,根节点最小的堆叫做最小堆或小根堆。常见的堆有二叉堆、斐波那契堆等。

8、图

图是由结点的有穷集合V和边的集合E组成。其中,为了与树形结构加以区别,在图结构中常常将结点称为顶点,边是顶点的有序偶对,若两个顶点之间存在一条边,就表示这两个顶点具有相邻关系。

⑶ 使用什么数据结构可以快速遍历查找的所需数据

最快的肯定是
散列
(也叫哈希),其次是
树形结构
,再其次是索引
顺序结构
(也叫作分块)

⑷ 数据库系统的实现中采用了哪些常用的数据结构

数据库索引文件采用数据结构概述: 1、非主键索引需要在数据表本身的存储空间外额外开销存储空间,所以在更新的时候可能不仅要更新数据表本身,还要更新非主键索引,更新内容更多了,所以导致速度降低。反过来,如果数据表中的数据按照主键索引的顺序存储,更新的时候就没有额外的开销。 非主键索引对提高查询速度来讲,主要的方面是:检索的条件(where...)如果命中对应的非主键索引的话,就不需要对数据表做全表扫描,效率肯定是大大提高。(索引的创建和使用是数据库设计和优化的重要部分,是一个数据库程序员的必修课,不同数据库系统的语法不同,但是原理基本相同); 2、如果检索结果的字段包含在非主键索引中,即使对非主键索引做全扫描,也比对整表字段做全扫描快,因为只有非主键索引本身的数据需要从存储设备调入内存,节约了IO时间。 3、不过一般说索引对查询速度的影响,主要指第一种情况。 关于数据库索引的数据结构,大多数数据库都是采用B树。可参照文章: 非主键索引需要在数据表本身的存储空间外额外开销存储空间,所以在更新的时候可能不仅要更新数据表本身,还要更新非主键索引,更新内容更多了,所以导致速度降低。反过来,如果数据表中的数据按照主键索引的顺序存储,更新的时候就没有额外的开销。 非主键索引对提高查询速度来讲,主要的方面是:检索的条件(where...)如果命中对应的非主键索引的话,就不需要对数据表做全表扫描,效率肯定是大大提高。(索引的创建和使用是数据库设计和优化的重要部分,是一个数据库程序员的必修课,不同数据库系统的语法不同,但是原理基本相同); 另一方面,也有如下的可能:如果检索结果的字段包含在非主键索引中,即使对非主键索引做全扫描,也比对整表字段做全扫描快,因为只有非主键索引本身的数据需要从存储设备调入内存,节约了IO时间。 不过一般说索引对查询速度的影响,主要指第一种情况。

⑸ 可持久化数据结构

最近在刷MIT 6.851,记录下笔记。

可持久化数据结构就是能存储、查询数据的历史版本的数据结构。

http://hypirion.com/musings/understanding-persistent-vector-pt-1

https://www.geeksforgeeks.org/persistent-data-structures/?ref=lbp

可持久化数据结构简介

MIT 6.854j-advanced-algorithms
很赞!!可惜没video。

Making Data Structures Persistent
太长没看

总结了下大致包括如下领域应用:

并发事务的原子性(便于Rollback)、隔离性。

https://io-meter.com/2016/09/03/Functional-Go-persist-datastructure-intro/

同上。

便于实现diff,rollback

可持久化数据结构最初设计出来的目的是为了在高维查询中降维,把其中一个维度当做时间,用可持久化数据结构处理效率更高
可以看下MIT 6.851老师的介绍。

这种思想在高维处理中很常见,比如求二维range sum query时候,把其中一个维度当时间、拿来做扫描线也是这种降维思路(见《算法竞赛进阶指南》):

可持久化数据结构简介

自己轮一个.net可持久化库 Persistent Data Structures 下面有讨论use case
中文翻译见 可持久化数据结构

Functional Go: 持久化数据结构简介

这部分可以看6.851视频

6.851把链式数据结构的模型叫pointer machine model。对于基于pointer machine model的数据结构,有没有通用的方法将他们改造成persistent?

note see https://ocw.mit.e/courses/electrical-engineering-and-computer-science/6-854j-advanced-algorithms-fall-2005/lecture-notes/persistent.pdf
video see https://www.bilibili.com/video/BV1iE411n7yJ

O(1)写,读时对于每个点都要执行O(logm)的查询。假设一次查询要读v个点,时间复杂度O(vlogm)
所以对写友好,对读不友好

看到这里有个问题:每个点的history放hashmap里不就行了?读时也只需要O(1)的查找
但这样做的话,hashmap不支持ceil操作,因此要支持ceil没办法只能用有序结构、log级别查询
(这里的假设是有个全局时间戳,而不是每个key对应一个自己的自增时间戳)

个人理解,想做可持久化key/value Map的话即可按这种方法,每个key对应的entry存放所有历史值,这也可以看成是邻接表。

说白了就是写时分裂节点,从root开始分裂到要写的点。将所有version的root存到字典里

上面两个要么对写不好,要么对读不好,能否兼得?

难以置信,说白了就是给path ing方法中每个node加一个log cache,最后算出来的写时amortized time complexity就是O(1)了。

What about non-tree data structures?

平衡树怎么处理?
平衡树要旋转,想想就感觉很难改造成持久化。6.854课件讲的很粗没懂。 算法竞赛中常用的可持久化平衡树一般就是 可持久化无旋转 Treap ,省去了旋转可持久化的复杂。

a. fat nodes
每个点存的log从version queue变成version tree,查询每个点时要从树中找到最近祖先

b. path ing
没区别

c. modification box
怎么找根节点?
i. pointer per version,可能多个pointer指向一个root
ii.存root tree,查询时先找最近祖先

怎么修改old version
i. 修改时放box,满了就分裂出来一个新节点

但这样有问题:分裂出来的还是满的,如果整条链都是满的,每次修改复制全部,下次修改还得复制全部。而且这样还不好存root,比如最右边图,代表0的root有俩

ii. 修改时放box,满了就分裂出来一个新节点,但分裂时自动apply有用的log、丢弃没用的log

What about non-tree data structures?
6.851有讲,分裂成两个节点,log分成两部分,新节点拿一个子树的log,新节点apply log直到自己的子树,每部分丢弃自己用不到的。

6.851讲了 太复杂没听懂。

网上关于可持久化数据结构的优质资料都是算法竞赛的,因此收集总结了下竞赛常用的。看了下基本都是partial persistent,有的是fully persistent,都没用到modification box技术。
https://github.com/Misaka233/algorithm/blob/master/%E9%99%88%E7%AB%8B%E6%9D%B0%EF%BC%9A%E5%8F%AF%E6%8C%81%E4%B9%85%E5%8C%96%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E7%A0%94%E7%A9%B6.pdf

https://www.bilibili.com/video/BV1C4411u7rK?p=1

https://www.geeksforgeeks.org/persistent-trie-set-1-introction/
和可持久化线段树类似的方法,基于path 实现partial persistence。
问题是每个点在拷贝时都要复制O(R)个指针,插入的时间复杂度为O(len*R)
查询时先从字典(数组/哈希表)里找到指定version的root,然后访问,O(len)

在竞赛中常用的是可持久化01字典树,比如xor问题,见 https://oi-wiki.org/ds/persistent-trie/ ,没看懂

算法竞赛中常用的可持久化平衡树一般就是 可持久化无旋转 Treap ,省去了旋转可持久化的复杂。

【AgOHの数据结构】可持久化数组

https://www.luogu.com.cn/problem/P3919

方案:
a. fat nodes
每个节点放所有历史,查询时在所有历史版本中找最近祖先版本

b. path ing
存到可持久化线段树里。
为什么好好的线性结构要树化?直觉上理解,是为了分裂新版本时减少指针复制。

如果是稀疏数组,朴素方法太浪费空间了,可以基于动态开点来优化空间存储,见 https://io-meter.com/2016/11/06/functional-go-intro-to-hamt/

【AgOHの数据结构】可持久化并查集

并查集基于数组,可持久化并查集就基于可持久化数组。可持久化数组用可持久化线段树实现,因此可持久化并查集用可持久化线段树实现

《 可持久化数据结构研究 》
不过文中写的太简略了,个人推测的维护方法为:

https://io-meter.com/2016/09/03/Functional-Go-persist-datastructure-intro/

讨论支持如下操作的抽象数据结构(ADT)如何可持久化:

a. 基于普通数组
只能 on write
b. 基于可持久化数组/可持久化线段树
问题是怎么处理新增节点、删除节点?得想办法魔改线段树
c. 可持久化链表
d. 可持久化块状链表
e. 可持久化平衡树
f. 文中提到的vector trie
名字挺骚的没反应过来,看了一会发现:这玩意就是可持久化数组(可持久化线段树),只不过是多叉树,叫“可持久化多叉线段树”比较形象。文章也没提怎么处理新增节点、删除节点。

persistent-hash-table-implementation
a. 可持久化平衡树
b. 还用hashmap,但是每个entry改造成fat node(存放所有log),查询时先找到entry,再在所有log 中找最近祖先版本
c. 可持久化数组。
考虑到HashMap本来就能只用一个数组实现(解决冲突时用open addressing方法,不用Chaining),那么实现了可持久化数组就相当于实现了可持久化HashMap

d. Hash_trie
hash(key)的值存在trie里,value放到trie的叶子节点。优化版本包括 Hash array mapped tries and Ctries
HAMT这名字起的很奇怪。原理就是块状hash trie(所谓块状是我自己起的名,指每个节点区分儿子时不是单纯的比较某1位,而是比较某2位甚至多位)(或者理解成hash trie+动态开点多叉线段树也行)(反正就是bitwise hash trie加上一堆优化,懒得记就记hash trie就行了,真要自己实现的时候这些优化trick也能想到)
文中讲hamt的碰撞处理有点扯,个人理解可以chaining,可以open addressing。细节没深究,可以看 论文 和 讨论 。按作者的意思AMT是之前他提出的一种Trie的优化,比Tenary search trie要好。

https://www.cnblogs.com/tedzhao/archive/2008/11/12/1332112.html

// TOOD

https://www.cnblogs.com/zinthos/p/3899565.html
Planar Point Location问题见
https://courses.csail.mit.e/6.851/spring12/scribe/lec3.pdf
https://www.bilibili.com/video/BV1iE411n7yJ?p=3

http://acrossthesky.logdown.com/posts/712254-some-basic-data-structures
https://github.com/Misaka233/algorithm/blob/master/%E9%99%88%E7%AB%8B%E6%9D%B0%EF%BC%9A%E5%8F%AF%E6%8C%81%E4%B9%85%E5%8C%96%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E7%A0%94%E7%A9%B6.pdf
https://download.csdn.net/download/u011808175/6477705

朴素的方法是线段树套线段树,以便支持二维RMQ,时间复杂度O(logN*logN)。
个人理解,最优的二维RMQ数据结构应该是用modification box实现的可持久化值域线段树,O(N)的构造时间、空间,O(logN)的查询。

如果统计操作具有“区间可加性”、“区间可减性”,那么该操作二维统计问题可以使用可持久化线段树。
range minimum query中的min()操作其实不具有区间可减性,但是range minimum query问题可以归约成range select query问题,进而可以归约成range count query问题,而count()操作具有区间可加减性,因此也能用可持久化线段树。
所以我们得到了一类二维统计问题的通用数据结构:对于可归约成具有“区间可加性”、“区间可减性”统计操作的二维统计问题,可以使用可持久化线段树存储,以便支持快速查询(统计)。

能否找到一类高维统计问题,具有通用的logN级别解?个人理解可以借鉴代数的思想,只要有区间可加减性的都能归约成K维RMQ问题,用modification box实现的可持久化值域线段树解决。
// TOOD 只是个人畅想,没细想。

bigtable(hbase)可以看成外存模型下的可持久化map:

但需要注意的是删除操作会真的删掉之前的老版本数据:

其实任何支持前缀匹配的db都能作为可持久化map,你只需要把rowkey设计成"key@@timestamp"即可
http://hbase.apache.org/book.html#reverse.timestamp

⑹ 数据结构中有哪些查找,他们分别适用于查询那种存储结构

最常见的:
顺序查找:适合顺序结构和链式结构
二分查找:适合顺序结构

其他的二叉查找树、B-树之类有自己的数据结构

⑺ 用C++如何实现数据的快速查找和存储

数据通过相应的数据结构存储,所以查找是在数据结构的基础上进行。 一般为了保证查找的效率通常使用顺序存储结构,比如数组等可直接通过下标获取元素的结构。
存储一般考虑需求,如果后面有大量插入删除操作则选择链表等结构
望采纳