想象你在经营一座万国仓储物流中心。每天清晨,来自四面八方的货车同时抵达:有的是整齐划一的集装箱,装着标准规格的工业零件——这就像交易所的行情数据;有的是大小不一、形状各异的快递包裹,里面是用户评论、卫星照片、天气报告——这就是我们今天的主角“另类数据”。你的仓库若想通吃所有货物,会发现传统那种“每个格子尺寸固定”的九宫格货架根本装不下这些奇形怪状的东西。于是你引入两套专用设施:一套是“高密度动态货架”(宽列存储 HBase),每件货物都有自己的货位编号和时间标签,随到随放;另一套是“全球供应链关系地图”(图数据库 Neo4j),把客户、供应商、银行、物流之间的往来关系连成一张活地图。今天的主题,就是这套“货架 + 地图”的 NoSQL 存储方案,如何支撑金融领域的另类数据应用。

岗位关联

掌握另类数据的 NoSQL 存储架构设计,能让你在金融数据平台、量化投研、风控反欺诈等场景中快速选对存储引擎,是数据工程师与架构师的硬核技能。

目录
  1. 可视化演示
  2. 另类数据概貌
  3. 存储挑战与NoSQL选型
  4. 宽列存储原理HBase
  5. 图数据库原理Neo4j
  6. 建模设计实战
  7. 混合架构实践
  8. AI 应用场景
  9. Python 演示
  10. 常见误区
  11. 面试题

可视化演示

通过步进式演示展示算法的执行过程,包括元素比较、交换和最终排序结果,支持自动播放和手动控制。

本节配有交互动效(进入视口后自动加载,约 3KB)。

冒泡排序演示 紫色柱表示当前正在比较的元素 粉色柱表示即将交换的位置 比较相邻元素,若前>后则交换 逐步完成排序过程。

另类数据概貌

万国仓储里的货物品类千姿百态:有的来自卫星对地面的遥感拍摄,记录停车场车辆数量的变化;有的来自社交媒体的每一条发帖,承载市场情绪的温度;还有的来自移动设备的定位轨迹,刻画人们出行的节律。这些不在传统财报和行情范围内的货物,共同拥有一个名字——另类数据(Alternative Data)。它们单独看像是散落的边角料,放在一起却能拼出一幅更完整的市场图景。

在金融语境下,另类数据指传统交易所行情、上市公司财务报表之外的数据源,包括航运卫星图像、电商订单、招聘广告、信用卡流水、舆情评论、APP 下载量等。它们的共同点在三个维度上非常突出:数据量巨大,每天光一个数据源就可能产生几十到上百 GB;结构千奇百怪,既有规范的 JSON、CSV,也有自由文本、图像和轨迹点;更新极其频繁,从秒级行情到分钟级舆情,稍有延迟价值就大打折扣。

技术圈把这三个特点概括为“3V“模型,它是判断”要不要用 NoSQL”的第一把尺子。

回到仓储中心的比喻:这三类特征就像“包裹多、形状怪、来得急”。如果你只有普通货架,搬运工刚把货物分类登记完,下一批车又堵在门口了。所以第一步,就是认清你的货物到底有多"3V",这决定了后面选什么样的仓库。

另类数据=量大⏟Volume+繁杂⏟Variety+快变⏟Velocity\displaystyle \text{另类数据} = \underbrace{\text{量大}}_{\text{Volume}} + \underbrace{\text{繁杂}}_{\text{Variety}} + \underbrace{\text{快变}}_{\text{Velocity}}
3V 不是三个孤立的形容词,而是互相叠加的压力:又大、又杂、又快,三者同时出现,传统存储才会真正吃不消。
  1. 量大(Volume)指数据总体规模达到 PB 级,单日新增量也很惊人,要求存储系统具备水平扩展能力。
    Volume=每天新增×保留天数\text{Volume} = \text{每天新增} \times \text{保留天数}
  2. 繁杂(Variety)指数据类型横跨文本、图像、时序、轨迹等,字段结构不统一,需要 schema 灵活。
    Variety={文本,图像,时序,轨迹}\text{Variety} = \{ \text{文本}, \text{图像}, \text{时序}, \text{轨迹} \}
  3. 快变(Velocity)指数据产生和更新的速率快,需要秒级到分钟级的写入与读取能力。
    Velocity=ΔDataΔt↑\text{Velocity} = \frac{\Delta \text{Data}}{\Delta t} \uparrow

存储挑战与NoSQL选型

传统关系型数据库就像一间“九宫格仓库”:每格大小提前画好,货物入库前必须先量体裁衣。对于行情和账本这类规矩数据,这套流程高效可靠;但面对另类数据,问题立刻暴露——卫星图像往哪个格子里放?一篇舆情该分几列?推特上的字段今天三个键、明天五个键,难道每周都要拆掉隔板重装一遍?

更棘手的是写入吞吐。关系型数据库为了保证 ACID 事务,写入要走锁、日志、索引多道工序,单机写入上限往往只有每秒几千到几万条。而另类数据管道经常以每秒几十万条的速度涌入,高速公路上开马车,再好的马也跑不出物流公司的时效。同时,另类数据很少有跨行强事务需求,这恰恰说明我们应该换一种存储哲学。

从深层次看,这是一次从“写入时定结构”到“读取时定结构”的范式切换。传统数据库使用 Schema-on-Write,数据进来之前必须先建好表;NoSQL 使用 Schema-on-Read,先把数据存下来,等要分析时再按需解释结构。这一转变,让存储系统从“挑剔的仓库管理员”变成“来者不拒的收件员”。

选型时的一句口诀是“先看查询,再定存储”。你的另类数据主要是按 key 高频读写,那就选宽列存储(HBase);如果要分析实体之间的多跳关系,那就选图数据库(Neo4j)。就像仓库里既有货架又有地图:你知道货物放在哪一层,就用货架;你想知道货物流向哪些客户,就查地图。

Schema-on-Write (传统关系型)→Schema-on-Read (NoSQL)\displaystyle \text{Schema-on-Write}\ (\text{传统关系型}) \rightarrow \text{Schema-on-Read}\ (\text{NoSQL})
范式切换的本质是“先收下再说,需要时再整理”,这与另类数据“量大、杂乱、来得急”的特点是绝配。
  1. Schema-on-Write写入前必须定义好表结构,像仓库要求所有货物都按固定箱子交货。
    写入前:建表→校验→入库\text{写入前}: \text{建表} \rightarrow \text{校验} \rightarrow \text{入库}
  2. Schema-on-Read写入时不限制格式,读取时按业务需要动态解析字段。
    读取时:原样存储→按需解析\text{读取时}: \text{原样存储} \rightarrow \text{按需解析}
  3. 范式切换的代价与回报放弃了强事务和标准 SQL,换来了海量写入和灵活扩展的能力。
    ACID→BASE(最终一致)\text{ACID} \rightarrow \text{BASE} \quad (\text{最终一致})

宽列存储原理HBase

宽列存储 HBase 在物流中心的定位,是那套“高密度自动货架”。它每一格不要求固定尺寸,而是把同一个“列族”的货物就近码放。列族就像仓库里的几个大区域:行情区、舆情区、交易区。区域是建仓时划好的,但区域里具体放什么品类、放多少排,完全可以在运营中动态调整。

HBase 的数据模型可以用一个“定位公式”来理解。每一份数据都通过四个要素唯一定位:行键(RowKey)、列族(Column Family)、列限定符(Qualifier)、时间戳(Timestamp)。这就像你的货物在仓库中的完整坐标:哪个巷道、哪个货区、哪个层板、什么时间放进去的。

在实际应用中,行键设计是建模的第一要务,也是最容易踩坑的地方。常见的套路是“哈希散列 + 时间倒序”:把来源 ID 做哈希前缀以均匀分散写入压力,把时间戳反转放在后面,让同一实体的最新数据排在前面,便于倒序扫描。

回到货架本身,列族的划分也很讲究。列族数量通常控制在三五个以内,因为每个列族对应独立的存储文件,列族太多会造成大量小文件,拖慢读写性能。把更新频率相近的字段放进同一列族,就像把保质期相近的食品放在同一排货架,仓库才能高效运转。

RowKey=Salt(SourceID)⏟散列防热点+Reverse(EventTime)⏟时间倒序\displaystyle \text{RowKey} = \underbrace{\text{Salt}(\text{SourceID})}_{\text{散列防热点}} + \underbrace{\text{Reverse}(\text{EventTime})}_{\text{时间倒序}}
行键是宽列存储的“地址簿”,设计得好,查询快如闪电;设计得差,全表扫描慢如蜗牛。
  1. 散列防热点(Salt)对 SourceID 做哈希并截取前缀,让海量写入均匀分布到不同 Region,避免单点过热。
    Salt=Hash(SourceID) mod N\text{Salt} = \text{Hash}(\text{SourceID}) \bmod N
  2. 时间倒序(Reverse)将时间戳按最大值取反,让时间上越新的数据,在有序扫描中越靠前。
    Reverse(T)=Tmax−T\text{Reverse}(T) = T_{\text{max}} - T
  3. 拼接成行键将散列前缀与倒序时间拼接,得到唯一且有序的 RowKey。
    RowKey=Salt⊕Reverse(T)\text{RowKey} = \text{Salt} \oplus \text{Reverse}(T)

图数据库原理Neo4j

如果说 HBase 是高密度货架,那么 Neo4j 就是挂在仓库墙上的“供应链地图”。这张地图不关心每一箱货本身长什么样,它只关心货从哪里来、经过谁的手、最终到了哪里。图的视角天然适合表达“关系”:公司控股公司、供应商供货给制造商、客户与客户之间有担保关联。

在 Neo4j 中,数据被建模为节点(Node)和边(Relationship)。节点代表公司、个人、产品等实体;边代表实体之间的关系,并且可以带方向和属性。比如“甲公司投资了乙公司”,在图上就是一个“甲”节点,通过一条“投资”边,指向“乙”节点。这种结构看起来简单,却让多跳查询变得极其高效:从某个节点出发,沿着边连续走几步,就能发现隐藏在长链条背后的关联。

Cypher 是 Neo4j 的查询语言,它的核心语法像画画一样直观。下面这条查询,意思是从“公司”标签中找节点 a,沿着“投资”边找到 b,然后返回 b:

在金融风控中,这种多跳查询的价值立竿见影:识别洗钱团伙时,警方关注的是账户之间的资金往来网络;识别担保圈风险时,监管方要看的是企业之间的互保链条。这些场景用 SQL 可能需要十几次自连接,而在图数据库里一条 Cypher 就能完成。

MATCH (a:公司)−[r:投资]→(b:公司) RETURN b\displaystyle \text{MATCH}\ (a:\text{公司})-[r:\text{投资}] \rightarrow (b:\text{公司})\ \text{RETURN}\ b
这行查询就像在地图上顺着一条红色箭头走:起点是投资方,终点是被投公司,箭头沿途的方向就是关系的方向。
  1. MATCH 匹配声明要从图中找出符合某种连接模式的子图,是 Cypher 的查询入口。
    MATCH ⟨模式⟩\text{MATCH} \ \langle \text{模式} \rangle
  2. 节点与标签(a:公司) 表示一个带有“公司”标签的节点,并把它存入变量 a。
    (a:Label)(a : \text{Label})
  3. 有向关系-[r:投资]-> 表示一条类型为“投资”的有向边,方向从 a 指向 b,关系存入变量 r。
    −[r:Relation]→-[r : \text{Relation}] \rightarrow
  4. RETURN 返回将命中的节点或属性作为查询结果输出。
    RETURN b.name\text{RETURN}\ b.\text{name}

建模设计实战

现在回到仓储中心的操作手册。我们已经有了两套设施——宽列货架 HBase 和供应链地图 Neo4j,关键问题变成:每一批货物该送进哪一个设施?答案取决于“查询模式”:如果你需要按 ID 和时间快速读写明细,就去 HBase;如果你想分析实体之间的关联路径,就去 Neo4j。这就像仓库的分拣员,看一眼面单上的目的地,就知道该把包裹送上哪条传送带。

对于文本类另类数据(新闻、舆情、公告),建模时通常把“来源 + 时间”作为行键,把标题、正文、情感分数、实体标签等字段分别放进不同的列族。这样设计的好处是:读取某一天的舆情时,只需按行键前缀扫描,无需全表扫描。对于交易流水、卫星遥感计数这类时序数据,同样按“日期 + 标的 ID”组织行键,再按天做分区管理,过期数据直接整区删除。

对于实体关系类数据(供应链上下游、股权结构、担保关系),则要构建“图模型”。以一家上市公司为中心,把它关联的供应商、客户、银行、子公司全部建模成节点,把供货、借贷、控股等业务往来建模成边。Node 上保存实体的静态属性,Edge 上保存关系的动态属性(如金额、日期)。

实践中的一条重要经验是“时间分区”。另类数据的价值随时间衰减很快,半年前的舆情对当前交易策略几乎没有参考意义。在 HBase 里按天建分区,配合 TTL 自动过期;在 Neo4j 里为关系边打上时间属性,查询时按时间窗口过滤。仓储中心的冷热分区也是同一逻辑:热销品放最外层货架,滞销品进冷库,到期自动清仓。

存储路由={文本 / 时序→HBase 宽表实体 / 关系→Neo4j 图\displaystyle \text{存储路由} = \begin{cases} \text{文本 / 时序} \rightarrow \text{HBase 宽表} \\[6pt] \text{实体 / 关系} \rightarrow \text{Neo4j 图} \end{cases}
建表之前先问一句“我要怎么查”:按 key 查就进宽表,沿着关系查就进图库。
  1. 文本/时序入宽表高频读写、按 key 定位的场景,落到 HBase 宽表。
    RowKey=SourceID+Date\text{RowKey} = \text{SourceID} + \text{Date}
  2. 实体/关系入图谱多跳关联分析场景,落到 Neo4j 图模型。
    G=(V实体, E关系)G = (V_{\text{实体}},\ E_{\text{关系}})
  3. 路由决策依据以查询模式为唯一标准,数据本身不是决定因素。
    Query Pattern⇒Storage Choice\text{Query Pattern} \Rightarrow \text{Storage Choice}

混合架构实践

真正生产级的另类数据平台,几乎从来不只用一套存储。宽列货架负责“存得多、读得快”,供应链地图负责“看得清、查得深”,两者组合才构成完整的仓储体系。数据从源头出发,先经过接入层进入 HBase 持久化,再通过异步 ETL 抽取关键实体和关系,同步到 Neo4j 构图。整个过程像一条流水线:货物先入库,再贴标签,最后上地图。

这套混合架构的关键在于“双引擎协同”的边界划分。HBase 承担实时摄入和明细查询,是系统的“事实数据源”;Neo4j 承担关系分析和路径挖掘,是系统的“关系推理层”。两边的数据通过一致的业务主键(如公司 ID、交易 ID)关联,互不越界。常见错误是让 Neo4j 承担明细存储或让 HBase 做多跳遍历,这就像让地图去搬货、让货架去指路,都会力不从心。

数据管道是连接两套引擎的桥梁,通常的做法是:写入 HBase 后,通过订阅日志或定时批任务,把新增数据解析成节点和边,以幂等方式写入 Neo4j。幂等写非常重要——同一份数据被重复处理时,图库里的结果不能翻倍。用“合并”语义(MERGE)而不是“创建”语义(CREATE),就是这个环节的保底保险。

回到万国仓储中心的画面:一位基金经理早上来到控制台,先在 HBase 上快速拉取过去一小时全网舆情明细,再切到 Neo4j 查看某家被投公司的关联企业图谱。货架给了他“快”,地图给了他“深”。一个成熟的数据平台,就是让每一类数据都住在最合适的仓库里,各司其职,协同运转。

写路径: 数据源→实时摄入HBase→异步ETLNeo4j\displaystyle \text{写路径}:\ \text{数据源} \xrightarrow{\text{实时摄入}} \text{HBase} \xrightarrow{\text{异步ETL}} \text{Neo4j}
混合架构不是简单地把两套库拼在一起,而是让数据按各自擅长的方向分流,最终在查询层汇合。
  1. 实时摄入到 HBase所有原始数据先进入 HBase,利用高吞吐特性快速落盘。
    Ingest:Source→HBase\text{Ingest}: \text{Source} \rightarrow \text{HBase}
  2. 异步 ETL 构图由管道任务读取 HBase 增量数据,提取实体和关系,写入 Neo4j。
    ETL:HBase→Neo4j\text{ETL}: \text{HBase} \rightarrow \text{Neo4j}
  3. 统一查询视图应用层根据业务需求路由到不同引擎,必要时做跨引擎结果合并。
    Query=HBase(明细)∪Neo4j(关系)\text{Query} = \text{HBase}(\text{明细}) \cup \text{Neo4j}(\text{关系})

AI 应用场景

量化投研舆情因子管道

阶段:数据接入与存储

解决的问题:传统方案用关系型数据库存舆情文本,字段一变就要改表,且写入速率跟不上微博、新闻的实时推送,经常出现“数据还没存完,舆情已经过时”的尴尬。

具体案例:某量化私募搭建舆情因子平台,把全市场新闻、股吧帖子、Twitter 数据接入 Kafka,实时写入 HBase 按“来源+日期”组织行键,情感分数、实体标签作为动态列存储。每天新增数百 GB 数据,查询延迟从秒级降到毫秒级。

供应链金融反欺诈图谱

阶段:关系建模与分析

解决的问题:供应链金融的风险往往藏在关联关系中:A 公司担保 B 公司,B 公司又是 C 公司的股东,传统 SQL 需要十几次 join,写起来痛苦、跑起来缓慢。

具体案例:某银行将企业工商信息、担保记录、贸易流水导入 Neo4j,构建“企业-人-交易”知识图谱。反欺诈团队用 Cypher 查询担保环,发现多起“连环互保”骗贷案,把风控审查时间从三天缩短到三小时。

卫星遥感数据入库

阶段:存储选型与建模

解决的问题:卫星图像经过 AI 识别后产出停车场车辆数、矿井开工度、油罐储油量等结构化指标,数据量大、按时间和地点组织,不适合放在行式数据库。

具体案例:某金融数据服务商把商场停车场 AI 识别的客流数据按“城市+商场ID+日期”作为 RowKey 写入 HBase,配合时间分区与 TTL,半年数据可随时热查,为零售行业 ETF 提供另类因子。

Python 演示

python73 行
import timefrom collections import defaultdict  class SimpleHBase:    """Mini HBase: wide column + multi-version"""     def __init__(self):        self.tables = {}     def create_table(self, name, families):        self.tables[name] = {            "families": list(families),            "data": defaultdict(list),        }     def put(self, table, rowkey, family, qualifier, value, ts=None):        if ts is None:            ts = int(time.time() * 1000)        key = (rowkey, family, qualifier)        self.tables[table]["data"][key].append((ts, value))     def scan(self, table, family=None):        result = []        for (rowkey, fam, qual), versions in self.tables[table]["data"].items():            if family and fam != family:                continue            latest = sorted(versions, key=lambda x: -x[0])[0]            result.append((rowkey, f"{fam}:{qual}", latest[1]))        return result  class SimpleGraph:    """Mini graph db: nodes + edges + neighbour query"""     def __init__(self):        self.nodes = set()        self.edges = []     def add_edge(self, a, b, rel):        self.nodes.add(a)        self.nodes.add(b)        self.edges.append((a, rel, b))     def query(self, node, rel):        return [b for (a, r, b) in self.edges if a == node and r == rel]  def main():    hbase = SimpleHBase()    hbase.create_table("alt_data", ["news", "trade", "geo"])     hbase.put("alt_data", "row-0001", "news", "ticker", "AAPL")    hbase.put("alt_data", "row-0001", "news", "sentiment", "0.87")    hbase.put("alt_data", "row-0002", "trade", "notional", "1.2M")    hbase.put("alt_data", "row-0002", "geo", "car_count", "2031")     print("== HBase wide-column scan ==")    for row in hbase.scan("alt_data"):        print(row)     graph = SimpleGraph()    graph.add_edge("Apple", "Foxconn", "supplies")    graph.add_edge("Apple", "Bank", "borrows_from")    graph.add_edge("Foxconn", "Bank", "borrows_from")     print("== Neo4j-like relation query ==")    print("Apple supplies ->", graph.query("Apple", "supplies"))    print("Bank lends to ->", graph.query("Bank", "borrows_from"))  if __name__ == "__main__":    main()
目的:用两个轻量类模拟 HBase 宽列存储和 Neo4j 图存储的核心读写逻辑,演示另类数据“文本时序入宽表、实体关系入图谱”的建模思路。
  1. self.tables[name]["data"][key].append((ts, value))以(RowKey、列族、限定符)三元组定位单元格,模拟宽列多版本写入。
  2. latest = sorted(versions, key=lambda x: -x[0])[0]按时间戳降序取最新版本,对应 HBase 的“读取最新值”语义。
  3. self.edges.append((a, rel, b))用三元组保存一条有向边,这就是图数据库中关系的最小单元。
  4. return [b for (a, r, b) in self.edges if a == node and r == rel]正是 Cypher 中 MATCH (a)-[:rel]->(b) 的邻居查找逻辑。

常见误区

误区HBase 的列可以动态增加,那就不用提前设计表结构了,随便往里塞数据就行,反正都能存。

正解HBase 确实允许列限定符动态扩展,但列族(Column Family)必须预先定义,行键(RowKey)的设计更是直接决定读写性能。就像仓库可以放不规则货物,但货架区域和货位编号体系必须先规划好,否则货物进来之后只能堆在地上。

为何常见:宽列表现出的高灵活性让初学者误以为完全不需要设计,实际是把“列灵活”误解成了“表无约束”。

误区Neo4j 查询关系那么强大,把全部数据都放进去,就一劳永逸了。

正解图数据库擅长多跳关系查询,但单条数据的高吞吐写入和按 key 的明细查询并不擅长。全量数据入图会导致存储膨胀、写入变慢、查询退化。正确做法是“宽列存实体、图库存关系”,让两套引擎各司其职。

为何常见:图查询结果直观、性能惊艳,容易让人高估它的通用性,忽略了它也是“有专长、也有短板”的存储引擎。

误区反正数据都进了 HBase,查询时直接扫描全表不就行了?以前用 MySQL 也经常这么干。

正解全表 Scan 是宽列存储的大忌。HBase 没有关系型数据库那样的优化器,没有按 RowKey 定位的查询会退化成全库扫描,秒级查询变成分钟级灾难。行键设计(哈希前缀、时间反转)是建模第一要务。

为何常见:习惯了关系型数据库的“无条件查询+优化器兜底”思维,把行式经验直接搬到了列式分布存储上。

误区另类数据获取成本低,那就多存几个备份,防止丢失,反正硬盘便宜。

正解另类数据的成本大头不在存储而在加工与治理。多份拷贝若没有清晰生命周期和一致性管理,反而会形成“数据沼泽”。合理做法是分层管理:原始区、清洗区、特征区各设保留策略,配合 TTL 自动过期。

为何常见:只看到存储单价便宜,忽视了冗余数据带来的一致性维护、检索变慢和治理成本。

面试题

Q1. 另类数据的"3V"特征不包含以下哪项?

单选题 · easy

  • A.数据规模巨大
  • B.数据结构繁杂
  • C.数据强一致性← 正确答案
  • D.数据更新快速

答案:C。3V 指量大(Volume)、繁杂(Variety)、快变(Velocity),这是另类数据固有的三个属性。“强一致性”是存储系统需要额外提供的能力,而不是另类数据自身的特点,正如仓库不会要求货物自带货架。

Q2. HBase 行键中加入 Salt(散列前缀)的主要目的是?

单选题 · mid

  • A.提升单点查询速度
  • B.分散写入热点压力← 正确答案
  • C.压缩存储空间占用
  • D.保证数据安全加密

答案:B。Salt 的作用是把海量写入均匀分散到不同 Region 上,避免所有写请求都打在同一台机器上造成热点。它不改变查询逻辑、不压缩数据、也不负责加密,就像给货物加上随机巷道号,让搬运工分散到不同货区,而不是挤在同一条通道上。

Q3. 宽列存储(如 HBase)适合哪类应用场景?

多选题 · mid

  • A.时序日志的高效存储← 正确答案
  • B.多跳关系的复杂查询
  • C.字段动态扩展的数据← 正确答案
  • D.跨行强事务的账本

答案:AC。HBase 天然适合时序日志和动态字段的场景,灵活列加时间戳多版本是它的强项。多跳关系查询是图数据库的主场,跨行强事务则是传统关系型数据库的看家本领。选型就像分拣货物:按 key 存的走上层货架,查关系的走地图。

Q4. 在“万国仓储”比喻中,图数据库 Neo4j 对应哪类设施?

单选题 · easy

  • A.高密度自动货架
  • B.全球供应链地图← 正确答案
  • C.九宫格固定仓库
  • D.快递分拣传送带

答案:B。Neo4j 的核心是关系,就像一张供应链地图,关注的是“谁连接谁”;HBase 才对应高密度自动货架,关注的是“货物放在哪”。固定仓库比喻关系型数据库,传送带则更接近消息队列。

Q5. 另类数据为什么难用传统关系型数据库存储?

多选题 · mid

  • A.实时写入吞吐过高← 正确答案
  • B.字段结构频繁变化← 正确答案
  • C.数据规模无限增长← 正确答案
  • D.需要大量多表连接

答案:ABC。关系型数据库的 ACID 事务和高索引开销限制了写入吞吐,固定 Schema 无法适应字段频繁变化,单机扩展能力也跟不上数据规模的爆炸式增长。而“多表连接”恰恰是关系型数据库擅长的事,不是另类数据的痛点。

Q6. 在混合存储架构中,舆情文本一般存入 HBase,主要原因是?

单选题 · mid

  • A.需要多跳关联遍历
  • B.高频键值读写友好← 正确答案
  • C.保证强事务一致性
  • D.依赖全文搜索能力

答案:B。舆情文本按“来源+时间”组织行键,高频写入和范围读取非常契合宽列模型。多跳遍历是图数据库的菜,强事务一致性不是另类数据场景的刚需,全文搜索则应该交给搜索引擎。选 HBase,是因为它接得住“快进快出”的货。

Q7. Cypher 查询 MATCH (a:公司)-[:投资]->(b:公司) RETURN b 返回的是?

单选题 · mid

  • A.投资关系的总条数
  • B.被投资方的公司名← 正确答案
  • C.投资方公司的名称
  • D.全图中的公司总数

答案:B。Cypher 的模式中,a 是起点(投资方),b 是终点(被投资方),RETURN b 返回的是箭头指向的公司节点。就像在地图上从 A 城沿箭头走到 B 城,你问的是“终点是哪座城”,自然返回 B 城。

Q8. 图数据库在金融风控中的一个典型应用是?

单选题 · hard

  • A.存储每日行情快照
  • B.挖掘担保圈风险← 正确答案
  • C.批量计算信用评分
  • D.持久化交易流水

答案:B。担保圈的本质是“公司担保公司”的多跳关系,图数据库能高效发现环状担保网络,这是关系型数据库很难优雅实现的。行情快照和交易流水适合宽列存储,信用评分则是模型计算层的任务,不属于存储选型问题。

Q9. 宽列存储(HBase)与图数据库(Neo4j)的典型分工是?

多选题 · hard

  • A.HBase 存属性,Neo4j 存关系← 正确答案
  • B.HBase 实时摄入,Neo4j 关系分析← 正确答案
  • C.HBase 全表扫描,Neo4j 点查更新
  • D.HBase 存关系,Neo4j 存原始数据

答案:AB。经典混合架构中,HBase 负责海量明细的实时摄入与属性存储,Neo4j 负责实体之间的关系分析与多跳遍历。C 把两者的劣势描述成优势,D 则彻底颠倒了角色分工,就像让货架去画地图、让地图去搬货。

Q10. 要实现“按交易日倒序快速读取某标的的全部另类数据”,HBase 行键设计最合理的是?

单选题 · extreme

  • A.时间戳加标的ID正序
  • B.标的ID加时间戳倒序← 正确答案
  • C.随机UUID作为主键ID
  • D.倒序时间加标的哈希

答案:B。行键要同时满足“按标的过滤”和“时间倒序”两个要求。以标的ID开头能让同一标的数据落在连续范围内,再用时间戳倒序让最新数据排在前端;A 按时间开头会导致同一标的数据散落全表,C 无法按标的定位,D 同样牺牲了标的维度。这就是行键设计的核心权衡。