二级索引在 Cassandra 中如何工作?

2024-02-21

假设我有一个列族:

CREATE TABLE update_audit (
  scopeid bigint,
  formid bigint,
  time timestamp,
  record_link_id bigint,
  ipaddress text,
  user_zuid bigint,
  value text,
  PRIMARY KEY ((scopeid, formid), time)
  ) WITH CLUSTERING ORDER BY (time DESC)

有两个二级索引,其中record_link_id是一个高基数列:

CREATE INDEX update_audit_id_idx ON update_audit (record_link_id);

CREATE INDEX update_audit_user_zuid_idx ON update_audit (user_zuid);

据我所知,Cassandra 将创建两个隐藏的列族,如下所示:

CREATE TABLE update_audit_id_idx(
    record_link_id bigint,
    scopeid bigint,
    formid bigint,
    time timestamp
    PRIMARY KEY ((record_link_id), scopeid, formid, time)
);

CREATE TABLE update_audit_user_zuid_idx(
    user_zuid bigint,
    scopeid bigint,
    formid bigint,
    time timestamp
    PRIMARY KEY ((user_zuid), scopeid, formid, time)
);

Cassandra 二级索引作为本地索引实现,而不是像普通表那样分布。每个节点仅存储其所存储数据的索引。

考虑以下查询:

select * from update_audit where scopeid=35 and formid=78005 and record_link_id=9897;
  1. 该查询将如何在 Cassandra 中“幕后”执行?
  2. 高基数列索引 (record_link_id)影响其性能?
  3. Cassandra 会触及上述查询的所有节点吗?Why?
  4. 首先执行哪个条件,基表partition_key还是二级索引partition_key? Cassandra 将如何将这两个结果相交?

select * from update_audit where scopeid=35 and formid=78005 and record_link_id=9897;

上述查询在 cassandra 内部如何工作?

本质上,分区的所有数据scopeid=35 and formid=78005会被返回,然后通过record_link_id指数。它将寻找record_link_id条目为9897,并尝试匹配与返回的行匹配的条目,其中scopeid=35 and formid=78005。将返回分区键和索引键的行的交集。

对于上述查询,高基数列 (record_link_id) 索引将如何影响查询性能?

高基数索引本质上为主表中的(几乎)每个条目创建一行。性能会受到影响,因为 Cassandra 设计为对查询结果执行顺序读取。索引查询本质上是强制 Cassandra 执行random读。随着索引值基数的增加,查找查询值所需的时间也会增加。

cassandra 是否会触及上述查询的所有节点?为什么?

不。它应该只触及负责的节点scopeid=35 and formid=78005分割。索引同样存储在本地,仅包含对本地节点有效的条目。

在高基数列上创建索引将是最快、最好的数据模型

这里的问题是该方法无法扩展,并且如果update_audit是一个大数据集。 MVP Richard Low 有一篇关于二级索引的精彩文章(Cassandra 二级索引的最佳选择 http://www.wentnet.com/blog/?p=77),特别是在这一点上:

如果您的表明显大于内存,则即使只返回几千个结果,查询也会非常慢。返回潜在的数百万用户将是灾难性的,即使它看起来是一个有效的查询。

...

实际上,这意味着索引对于返回数十个甚至数百个结果最有用。当您下次考虑使用二级索引时,请记住这一点。

现在,您首先通过特定分区进行限制的方法将会有所帮助(因为您的分区肯定应该适合内存)。但我觉得这里表现更好的选择是record_link_id集群键,而不是依赖二级索引。

Edit

即使我们提供主键,当有数百万用户时,在低基数索引上建立索引如何扩展

这取决于你的行有多宽。基数极低的索引的棘手之处在于,返回的行的百分比通常更大。例如,考虑一个宽行users桌子。您通过查询中的分区键进行限制,但仍然返回 10,000 行。如果您的索引类似于gender,您的查询将必须过滤掉大约一半的行,这不会很好地执行。

二级索引往往在(由于缺乏更好的描述)“中间道路”基数上效果最好。使用上面的宽行示例users表,索引country or state应该比索引表现得更好gender(假设大多数用户并不都居住在同一个国家或州)。

编辑20180913

对于第一个问题“上述查询在 cassandra 内部如何工作?”的回答,您知道分页查询时的行为是什么吗?

考虑下图,取自Java 驱动程序文档 https://docs.datastax.com/en/developer/java-driver/3.6/manual/paging/ (v3.6):

基本上,分页将导致查询自行分解并返回到集群以获取下一次结果迭代。超时的可能性较小,但性能会呈下降趋势,与总结果集的大小和集群中的节点数量成正比。

TL;博士;请求的结果越多,分布在更多的节点上,所需的时间就越长。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

二级索引在 Cassandra 中如何工作? 的相关文章

随机推荐

  • flutter-desktop-embedding 如何构建 exe 文件

    in 颤动桌面嵌入 https github com google flutter desktop embedding 我是windows环境 可以运行 但是不知道如何构建exe文件 我想知道该怎么办 If you flutter buil
  • 对 JSONP 请求的工作原理感到困惑

    我无法理解 jsonp 请求如何工作的细节 我已经阅读了包括 jsonp 上的 wiki 在内的多个资料来源 但对于在进行 jsonp 调用时回调实际上如何获取从服务器返回的函数仍然非常困惑 例如 在wiki中 请求的来源设置为 src h
  • 在不使用 GIT 的情况下将 WAR 文件部署到 Openshift?

    我想将 WAR 文件上传到我的开放式换档帐户 但这迫使我 使用 GIT 或 GITHUB here https www openshift com kb kb e1088 how to deploy pre compiled java ap
  • 从服务器获取数据时 Android 中的列表视图

    我正在尝试将数据异步填充到列表视图中 我正在从服务器检索数据作为 JSON 响应 MainActivity java public class MainActivity extends Activity url to make reques
  • Availability.h 类宏

    是否可以有一个自定义可用性宏 例如 OSX AVAILABLE STARTING 我需要它以同样的方式执行 我只需要更改它的名称以及参数的版本和数量 是的 当然了 Objective C 是 C 的严格超集 因此 C 宏非常适合您使用 并且
  • 如何预测 merMod 对象(lme4)的术语?

    对于简单的glm对象 我可以使用predict fit type terms 检索包含每个项的拟合值的矩阵 相当于什么lmer resp glmer适配型号 据我所知 predict merMod功能不支持type terms 相当于什么l
  • 如何为 Outlook 创建“Internet 日历订阅”?

    目前 用户添加了一个 新的互联网日历 但它是 ICS 文件的一次性下载 我希望用户单击一个按钮即可将其个人日历添加为 Outlook 订阅 我想要自动更新 互联网日历订阅 http office microsoft com en us ou
  • VBA-获取所有文件属性

    我想获取文件夹中所有文件的属性 我已经将其用于固定数量的属性 我唯一关心的是找到最后一个属性的索引 用于GetDetailsOf方法 以便我可以列出所有属性 下面的函数返回属性计数 但不正确 因为它基于最后一个非空属性名称 然而 有一些索引
  • TinyMCE 编辑器中的换行符在预览中显示额外的行,而不是在代码中

    我将 BBCode 插件与 TinyMCE 结合使用 发现预览和 HTML 代码之间的换行符显示不一样 我在编辑器窗口中有以下几行 This is line one This is line three 第二行是空的 当我在 HTML 中查
  • Flutter Web 调试正常,但构建 Web 显示空白页面

    flutter doctor result Flutter Channel dev 1 21 0 1 0 pre on Microsoft Windows Version 10 0 19041 388 locale en US Androi
  • APK Openssl 版本

    我很困惑 我最近创建了 Google Play 应用程序 但几个小时后 我在控制台中收到消息 指出我使用了错误的 OpenSSL 版本 解压缩 p YourApp apk 字符串 grep OpenSSL gives OpenSSL 1 0
  • 如何使用 cygwin 排序对第 n 列上的制表符分隔文件进行排序?

    我有一个巨大的制表符分隔文件 我想在其第二列上进行排序 我需要使用制表符作为 cygwin 排序中的字段分隔符 所以我需要这样的东西 sort t t k 2 2 in txt gt out txt 但命令提示符按字面意思计算 t 而不是作
  • Storm 和 Spring 4 集成

    我有一个 Storm 应用程序原型 它读取 STOMP 流并将输出存储在 HBase 上 它可以工作 但不是很灵活 我正在尝试以与我们其他应用程序更一致的方式设置它 但不太幸运地弄清楚当前与 Storm 的工作方式 我们使用 spring
  • 如何在 Forth 中比较两个字符串?

    我可以在if声明还是我应该创建一个辅助布尔变量 这是我到目前为止的代码 顺便一提 IOX 是从用户那里获取输入 var compile VARIABLE complile lock compile var realPass compile
  • 如何更改ggplot2中图例文本的大小?

    我使用下面的数据和代码得到了这个图 我希望能够更改图例文本的大小 A B M1 M3 我尝试使用 legend text element text size 0 5 但它没有改变 有什么建议如何减小 legend text 的大小吗 Cod
  • 解决“只能在类中初始化静态常量整型数据成员”编译错误

    以下创建全局对象会导致编译错误 include stdafx h include
  • 混合单独编译的对象

    让我来上课吧class Drawable 它可以有许多成员 成员函数 父类 也可以非常简单 对于这个例子来说 这并不重要 另外 假设它是某种 GUI 元素 然后 假设我有一个渲染引擎 它作为 GCC 库提供engine a 该库包含clas
  • Laravel 5.0.* 中间件在处理路由之前从 url 中删除前缀区域设置

    我正在寻找一种方法 使所有应用程序路由都具有多个区域设置 而不使用路由组 这是因为我使用了外部扩展包 这意味着路由在很多地方注册 本质上我想让 foo bar 以及 en foo bar de foo bar es foo bar 等都被
  • 查找 int 数组中的第一个重复项,java

    这是我遇到的一个常见面试问题 但我未能按照其要求的方式改进它 assume we have an int array int A we want to find the first duplicate entry 几乎每个人都会想到使用Ha
  • 二级索引在 Cassandra 中如何工作?

    假设我有一个列族 CREATE TABLE update audit scopeid bigint formid bigint time timestamp record link id bigint ipaddress text user