作为开源实时数据仓库,Apache Doris 提供丰富的索引选择来加速数据扫描和过滤。根据用户参与程度,可以分为内置智能索引和用户创建索引。前者是 Apache Doris 在数据摄取时自动生成的,例如 ZoneMap 索引和前缀索引,而后者是用户针对各种用例选择的索引,包括倒排索引和 NGram BloomFilter 索引。

这篇文章深入探讨了倒排索引和 NGram BloomFilter 索引,提供了将它们应用于各种查询。

示例数据集

测试数据集包含约 1.3 亿条亚马逊客户评论。这是几个 Snappy 压缩的 Parquet 文件,总大小为 37GB。以下是一些示例:
Sample Dataset

每行包含 15 列,包括 customer_idreview_idproduct_idproduct_categorystar_ rating review_headlinereview_body

其中许多列可以通过基于其结构的索引来加速。例如,customer_id 是一个高基数数字字段,而 product_id 是一个低基数固定长度文本字段,而 product_title 和 < code>review_body 分别是短文本字段和长文本字段。

对这些列的查询大致可以分为两种类型:

  • 文本搜索:搜索 review_body 字段中的某些内容。
  • 非主键列查询:查询有关特定product_id或来自特定customer_id的评论。

这些也是本文的主线。我将向您介绍索引如何加速这些查询。

先决条件

为了快速运行,这里我们使用单节点集群(1 个前端,1 个后端)。

  • 部署 Apache Doris:参考快速入门< /里>
  • 使用以下语句创建表:
  • SQL

     

    创建表 `amazon_reviews` (
      `review_date` int(11) NULL,
      `市场` varchar(20) NULL,
      `customer_id` bigint(20) NULL,
      `review_id` varchar(40) NULL,
      `product_id` varchar(10) NULL,
      `product_parent` bigint(20) NULL,
      `产品标题` varchar(500) NULL,
      `产品类别` varchar(50) NULL,
      `star_ rating`smallint(6) NULL,
      `helpful_votes` int(11) NULL,
      `total_votes` int(11) NULL,
      `vine` 布尔值 NULL,
      `verified_purchase` 布尔值 NULL,
      `review_headline` varchar(500) NULL,
      `review_body` 字符串 NULL
    ) 引擎=OLAP
    重复密钥(`review_date`)
    评论“OLAP”
    按哈希(`review_date`)分布 桶 16
    特性 (
    "replication_allocation" = "tag.location.default: 1",
    “压缩”=“ZSTD”
    );

  • 下载数据集:Snappy 压缩的 Parquet 文件,总大小为 37GB

  • 执行以下命令加载数据集
  •  

    curl --location-trusted -u root: -T amazon_reviews_2010.snappy.parquet -H "format:parquet" http://${BE_IP}:${ BE_PORT}/api/${DB}/amazon_reviews/_stream_load
    curl --location-trusted -u root: -T amazon_reviews_2011.snappy.parquet -H "format:parquet" http://${BE_IP}:${BE_PORT}/api/${DB}/amazon_reviews/_stream_load
    curl --location-trusted -u root: -T amazon_reviews_2012.snappy.parquet -H "format:parquet" http://${BE_IP}:${BE_PORT}/api/${DB}/amazon_reviews/_stream_load
    curl --location-trusted -u root: -T amazon_reviews_2013.snappy.parquet -H "format:parquet" http://${BE_IP}:${BE_PORT}/api/${DB}/amazon_reviews/_stream_load
    curl --location-trusted -u root: -T amazon_reviews_2014.snappy.parquet -H "format:parquet" http://${BE_IP}:${BE_PORT}/api/${DB}/amazon_reviews/_stream_load
    curl --location-trusted -u root: -T amazon_reviews_2015.snappy.parquet -H "format:parquet" http://${BE_IP}:${BE_PORT}/api/${DB}/amazon_reviews/_stream_load
    


  • 检查验证:完成上述步骤后,在MySQL客户端中执行以下语句检查数据集的大小。从下面可以看出,加载了 135589433 行,在 Apache Doris 中占用了 25.873GB,比原始 Parquet 文件小了 30%。
  • MySQL
     
    mysql> SELECT COUNT() FROM amazon_reviews; +------------+ |计数(*)| +------------+ | 135589433 | +------------+ 一组 1 行(0.02 秒) mysql> 显示来自 amazon_reviews 的数据; +----------------+----------------+------------------------+--- -----------+------------+------------+ |表名 |索引名称 |尺寸|副本计数 |行数 |远程尺寸 | +----------------+----------------+------------------------+--- -----------+------------+------------+ |亚马逊评论 |亚马逊评论 | 25.873 GB | 16 | 16 135589433 | 0.000 | 0.000 | |总计 | 25.873 GB | 16 | 16 | 0.000 | 0.000 +----------------+----------------+------------------------+--- -----------+------------+------------+ 2 行一组(0.00 秒)

    加速文本搜索

    无索引

    现在,让我们尝试在 review_body 字段上运行文本搜索。具体来说,我们正在尝试检索评论中包含关键字“is super Awesome”的前 5 个产品。结果应根据评论数量按降序排序。每个结果应包含产品 ID、随机选择的产品标题、平均星级和评论总数。

    这是查询语句:

    MySQL

     

    选择
        产品ID,
        任何(产品标题),
        AVG(star_ rating) AS 评级,
        COUNT() AS 计数
    从
        亚马逊评论
    在哪里
        review_body LIKE '%超级棒%'
    通过...分组
        产品编号
    订购依据
        计数 DESC,
        评级 DESC,
        产品编号
    限制 5;

    由于 review_body 字段包含冗长的评论,因此此类文本搜索可能非常耗时。在不启用任何索引的情况下,需要 7.6 秒返回结果:

    SQL

     

    +------------------------+------------------------ --------------------+--------------------+-------- +
    |产品 ID |任何值(产品标题)|评级|计数|
    +------------+------------------------------------ ------+--------------------+--------+
    | B00992CF6W | B00992CF6W |我的世界 | 4.8235294117647056 | 17 | 17
    | B009UX2YAC |地铁跑酷 | 4.7777777777777777 | 9 |
    | B00DJFIMW6 |小黄人快闪:卑鄙的我官方游戏 | 4.875 | 4.875 8 |
    | B0086700CM |神庙逃亡 | 5 | 6 |
    | B00KWVZ750 |愤怒的小鸟史诗角色扮演游戏 | 5 | 6 |
    +------------+------------------------------------ ------+--------------------+--------+
    一组 5 行(7.60 秒)

    NGram BloomFilter 索引

    现在,让我们尝试使用 NGram BloomFilter 索引加速此类文本搜索。

  • gram_size:“NGram”中“N”的值,表示连续字符的长度。在下面的代码片段中,"gram_size"="10" 表示文本将被分为许多 10 个字符的字符串,这是 NGram BloomFilter 索引的基础。
  • bf_size:BloomFilter 的大小(以字节为单位)。 "bf_size"="10240"表示BloomFilter占用10240字节的空间。
  • SQL

     

    使用 NGRAM_BF PROPERTIES("gram_size"="10", "bf_size"="10240") 更改表 amazon_reviews 添加索引 review_body_ngram_idx(review_body);< /前>
    


    这次,查询在0.93秒内完成。这意味着 NGram BloomFilter 带来了 8 倍的加速。

    SQL
     
    +------------------------+------------------------ --------------------+--------------------+-------- +
    |产品 ID |任何值(产品标题)|评级|计数|
    +------------+------------------------------------ ------+--------------------+--------+
    | B00992CF6W | B00992CF6W |我的世界 | 4.8235294117647056 | 17 | 17
    | B009UX2YAC |地铁跑酷 | 4.7777777777777777 | 9 |
    | B00DJFIMW6 |小黄人快闪:卑鄙的我官方游戏 | 4.875 | 4.875 8 |
    | B0086700CM |神庙逃亡 | 5 | 6 |
    | B00KWVZ750 |愤怒的小鸟史诗角色扮演游戏 | 5 | 6 |
    +------------+------------------------------------ ------+--------------------+--------+
    一组 5 行(0.93 秒)

    那么 NGram BloomFilter 是如何发挥魔力的呢? 它的工作方式可以分为两部分来解释。

  • NGram 标记化:当 gram_size=5 时,短语“hello world”被拆分为 [“hello”, “ello”, “llo w”、“lo wo”、“o wor”、“worl”、“世界”]。然后对这些子字符串进行哈希处理并将其添加到 bf_size 的 BloomFilter 中。由于 Apache Doris 中的数据是按页存储的,因此 BloomFilter 也是按页生成的。
  • 查询加速:例如查询文本中的单词“hello”,将“hello”进行标记并与每个页面的BloomFilter进行比较。如果 BloomFilter 检测到页面中的潜在匹配(可能存在误报),则会加载该页面以进行进一步匹配。否则,该页面将被跳过。
  • BloomFilter索引通过跳过不相关的页面,减少了不必要的数据扫描,从而大大降低了查询延迟。

    NGram BloomFilter 插图< /跨度>

    NGram BloomFilter 说明

    如何找到 NGram BloomFilter 的最佳参数配置

    gram_size决定匹配效率,而bf_size影响误报率。通常,较大的 bf_size 会降低误报率,但也需要更多的存储空间。因此,我们建议您根据以下两个因素来配置这两个参数:

    文本长度

    • 对于短文本(单词或短语),建议使用较小的 gram_size (2~4) 和较小的 bf_size
    • 对于长文本(句子或段落),较大的 gram_size (5~10) 和较大的 bf_size 效果更好。

    查询模式

    • 如果查询经常涉及短语或完整单词,则较大的 gram_size 会更有效。
    • 对于模糊匹配或多样化查询,较小的 gram_size 可以实现更灵活的匹配。

    倒排索引

    倒排索引 是加速文本搜索的另一种方法。创建倒排索引很简单:

  • 添加倒排索引:请参阅下面的代码段为 amazon_reviewsreview_body 列创建倒排索引代码>表。倒排索引支持短语搜索,其中标记词的顺序会影响搜索结果。
  • 为历史数据添加倒排索引:您还可以为历史数据创建倒排索引。
  • SQL

     

    更改表 amazon_reviews 添加索引 review_body_inverted_idx(`review_body`)
        使用反向属性("parser" = "english","support_phrase" = "true");
    在 amazon_reviews 上构建索引 review_body_inverted_idx;

  • 检查并验证:您可以使用以下语句检查并查看创建的索引:
  • MySQL

     

    mysql> 显示构建索引 WHERE TableName="amazon_reviews";
    +-------+----------------+----------------+----- -------------------------------------------------- -------------------------------------------------- ------------------------+------------------------- +------------------------+----------------+-------- ---+------+----------+
    |职位编号 |表名 |分区名称 |更改倒排索引 |创建时间 |完成时间 |交易ID |状态|留言 |进展|
    +-------+----------------+----------------+----- -------------------------------------------------- -------------------------------------------------- ------------------------+------------------------- +------------------------+----------------+-------- ---+------+----------+
    | 10152 | 10152亚马逊评论 |亚马逊评论 | [添加索引 review_body_inverted_idx (
    评论正文
    ) 使用反向属性("parser" = "english", "support_phrase" = "true")], | 2024-01-23 15:42:28.658 | 2024-01-23 15:48:42.990 | 11 | 11完成 | |空|
    +-------+----------------+----------------+----- -------------------------------------------------- -------------------------------------------------- ------------------------+------------------------- +------------------------+----------------+-------- ---+------+----------+
    一组 1 行(0.00 秒)

    如果您想了解标记化的工作原理,可以使用TOKENIZE函数进行测试。只需输入需要标记化的文本和参数即可:

    MySQL

     

    +------------------------------------------------ -------------------------------------------------- -------------------------------------------------- -------------------------------------------------- -------------------------------------------------- -------------------------------------------------- ----------+
    | tokenize('我可以诚实地给予发货和包装 100%,它准时到达,没有任何问题,而且这本书状况完美。超级棒的购买,非常适合我的大学课程', '"parser " = "english","support_phrase" = "true"') |
    +------------------------------------------------ -------------------------------------------------- -------------------------------------------------- -------------------------------------------------- -------------------------------------------------- -------------------------------------------------- ----------+
    | [“我”,“可以”,“诚实”,“给予”,“该”,“装运”,“和”,“包裹”,“100”,“它”,“来了”,“在”,“时间”、“那个”、“它”、“是”、“应该”、“到”、“与”、“不”、“哈塞尔”、“和”、“那个”、“书”、“是” 、“在”、“完美”、“状况”、“超级”、“棒极了”、“购买”、“和”、“优秀”、“对于”、“我的”、“学院”、“课程”] |
    +------------------------------------------------ -------------------------------------------------- -------------------------------------------------- -------------------------------------------------- -------------------------------------------------- -------------------------------------------------- ----------+
    1 行一组(0.05 秒)
    “ data-lang =“text / x-mysql”>

    mysql> SELECT TOKENIZE('我可以诚实地给予货物和包裹 100%,它准时到达,没有任何问题,而且这本书已经在完美的条件。
    超级棒的购买,非常适合我的大学课程', '"parser" = "english","support_phrase" = "true"');
    +------------------------------------------------ -------------------------------------------------- -------------------------------------------------- -------------------------------------------------- -------------------------------------------------- -------------------------------------------------- ----------+
    | tokenize('我可以诚实地给予发货和包装 100%,它准时到达,没有任何问题,而且这本书状况完美。超级棒的购买,非常适合我的大学课程', '"parser " = "english","support_phrase" = "true"') |
    +------------------------------------------------ -------------------------------------------------- -------------------------------------------------- -------------------------------------------------- -------------------------------------------------- -------------------------------------------------- ----------+
    | [“我”,“可以”,“诚实”,“给予”,“该”,“装运”,“和”,“包裹”,“100”,“它”,“来了”,“在”,“时间”、“那个”、“它”、“是”、“应该”、“到”、“与”、“不”、“哈塞尔”、“和”、“那个”、“书”、“是” 、“在”、“完美”、“状况”、“超级”、“棒极了”、“购买”、“和”、“优秀”、“对于”、“我的”、“学院”、“课程”] |
    +------------------------------------------------ -------------------------------------------------- -------------------------------------------------- -------------------------------------------------- -------------------------------------------------- -------------------------------------------------- ----------+
    1 行一组(0.05 秒)
    

    通过倒排索引,我们现在可以使用 MATCH_PHRASE 检索包含“is super Awesome”的客户评论。

    SQL

     

    选择
        产品ID,
        任何(产品标题),
        AVG(star_ rating) AS 评级,
        COUNT() AS 计数
    从
        亚马逊评论
    在哪里
        review_body MATCH_PHRASE '超级棒'
    通过...分组
        产品编号
    
    订购依据
        计数 DESC,
        评级 DESC,
        产品编号
    限制 5;

    子句 review_body MATCH_PHRASE 'is super Awesome' 搜索 review_body 列中包含所有三个关键字“is”、“super”和“awesome”的文本片段" 按照这个确切的顺序,中间没有其他单词。

    MATCH 查询不区分大小写,这也是它与 LIKE 查询的区别。 MATCH 查询在大型数据集中更加高效。

    结果显示,倒排索引将查询延迟降低至0.19秒,相比NGram BloomFilter索引带来4倍的性能提升,比完全没有索引的性能提升近40倍。

    SQL

     

    +------------------------+------------------------ --------------------+--------------------------------+-----+
    |产品 ID |任何值(产品标题)|评级|计数|
    +------------+------------------------------------ ------+--------------------+--------------------+
    | B00992CF6W | B00992CF6W |我的世界 | 4.833333333333333 | 18 | 18
    | B009UX2YAC |地铁跑酷 | 4.7 | 4.7 10 | 10
    | B00DJFIMW6 |小黄人快闪:卑鄙的我官方游戏 | 5 | 7 |
    | B0086700CM |神庙逃亡 | 5 | 6 |
    | B00KWVZ750 |愤怒的小鸟史诗角色扮演游戏 | 5 | 6 |
    +------------+------------------------------------ ------+--------------------+--------------------+
    一组 5 行(0.19 秒)

    倒排索引是如何实现的?

    倒排索引将文本拆分为单词并将每个单词映射到行号。然后,标记化的单词按字母顺序排序并创建跳跃列表索引。当执行特定单词的查询时,系统使用跳表索引和二分查找方法在这个有序映射中定位行号。根据行号,系统检索整个数据记录。

    这种方法避免了逐行匹配,并将计算复杂度从 O(n) 降低到 O(logn)。这就是倒排索引加速大型数据集查询的方式。

    倒排索引说明

    为了更深入地理解倒排索引,我将从它的读/写逻辑开始。在Doris中,从逻辑上讲,倒排索引应用在表的列级别。然而,从物理存储和实现的角度来看,它实际上是建立在数据文件之上的。

  • 写入:数据写入数据文件时,也会同步写入倒排索引文件,并匹配行号。
  • 查询:查询时,如果WHERE条件涉及到已建倒排索引的列,Doris会直接走到索引文件并返回相应的行号。然后,根据行号,它会跳过不相关的页和行,只读取目标行。
  • 简而言之,倒排索引通过映射实现高速文本搜索,其实现依赖于数据文件和索引文件的配合。

    加速非主键列查询

    为了展示倒排索引对非主键列查询的影响,让我们尝试一些多维查询。

    无索引

    检索客户 ID 13916588 关于产品 ID B002DMK1R0 的评论。如果没有索引,系统必须扫描整个表。查询在1.81秒内完成。

    MySQL

     

    mysql> 选择产品标题、评论标题、评论正文、星级评级
    来自亚马逊评论
    WHERE Product_id='B002DMK1R0' AND customer_id=13916588;
    +------------------------------------------------ ----------------+--------------------+---------- -------------------------------------------------- -------------------------------------------------- ---------------+-------------+
    |产品标题 |评论标题 |评论正文 |星级 |
    +------------------------------------------------ ----------------+--------------------+---------- -------------------------------------------------- -------------------------------------------------- ---------------+-------------+
    | Magellan Maestro 4700 4.7 英寸蓝牙便携式 GPS 导航仪 | Magellan Maestro 4700不错的功能但是... |这是一个很棒的 GPS。带您到达目的地。不过,不要忘记为交通套件购买单独的(哎呀!)电线! | 4 |
    +------------------------------------------------ ----------------+--------------------+---------- -------------------------------------------------- -------------------------------------------------- ---------------+-------------+
    一组 1 行(1.81 秒)

    倒排索引

    此查询的执行方式与上面所说的不同,因为系统不必对 product_idcustomer_id 进行标记,而是创建一个倒置的 Value→RowID索引表。

    首先,通过以下语句创建倒排索引:

    更改表 amazon_reviews 添加索引 Product_id_inverted_idx(product_id) 使用 INVERTED ;
    更改表 amazon_reviews 添加索引 customer_id_inverted_idx(customer_id) 使用 INVERTED ;
    在 amazon_reviews 上构建索引product_id_inverted_idx;
    在 amazon_reviews 上构建索引 customer_id_inverted_idx;

    使用倒排索引,相同的查询在0.06秒内完成。与之前的 1.81 秒相比,这意味着速度提高了30 倍

    MySQL

     

    mysql> 从 amazon_reviews 中选择product_title、review_headline、review_body、star_ rating,其中product_id='B002DMK1R0' AND customer_id='13916588'; +------------------------------------------------ ----------------+--------------------+---------- -------------------------------------------------- -------------------------------------------------- ---------------+-------------+ |产品标题 |评论标题 |评论正文 |星级 | +------------------------------------------------ ----------------+--------------------+---------- -------------------------------------------------- -------------------------------------------------- ---------------+-------------+ | Magellan Maestro 4700 4.7 英寸蓝牙便携式 GPS 导航仪 | Magellan Maestro 4700不错的功能但是... |这是一个很棒的 GPS。带您到达目的地。不过,不要忘记为交通套件购买单独的(哎呀!)电线! | 4 | +------------------------------------------------ ----------------+--------------------+---------- -------------------------------------------------- -------------------------------------------------- ---------------+-------------+ 一组 1 行(0.06 秒)

    简介

    这是 SegmentIterator Profile 的摘录,从中您可以了解为什么倒排索引可以加速查询执行。

    (注意,如果需要查看某个查询的Profile,请确保在执行该查询之前已在MySQL客户端中执行了SET enable_profile=true;,然后才能查看该查询的Profile位于http://FE_IP:FE_HTTP_PORT/QueryProfile

    SQL

     

    SegmentIterator:
      - FirstReadSeekCount:0
      - 首次读取查找时间:0ns
      - 首次读取时间:13.119ms
      - IO定时器:19.537ms
      - InvertedIndexQueryTime:11.583ms
      - 原始行读取:1
      - 筛选的行条件:0
      -行InvertedIndexFiltered:16.907403M(16907403)
      - 行ShortCircuitPredInput:0
      - RowsVectorPredFiltered:0
      - 行向量预测输入:0
      - 短预测评估时间:0ns
      - 总页数:27
      - 未压缩字节读取:3.71 MB
    - VectorPredEvalTime:0ns

    RowsInvertedIndexFiltered: 16.907403M (16907403)RawRowsRead: 1 表示倒排索引过滤掉了 16907403 行,只读取了 1 行(目标行)。 FirstReadTime: 13.119ms表示读取目标行所在页面需要13.119ms,InvertedIndexQueryTime: 11.583ms表示系统过滤掉16907403仅 11.58 毫秒内的行

    作为比较,这是不使用索引时的 SegmentIterator Profile:

    SQL

     

    SegmentIterator:
      - FirstReadSeekCount:9.374K (9374)
      - 首次读取搜索时间:400.522ms
      - 首次读取时间:3s144ms
      - IO定时器:2s564ms
      - InvertedIndexQueryTime:0ns
      - 原始行读取:16.680706M (16680706)
      - 筛选的行条件:226.698K (226698)
      - 行反向索引过滤:0
      - 行ShortCircuitPredInput:1
      - RowsVectorPredFiltered:16.680705M (16680705)
      - RowsVectorPredInput:16.680706M (16680706)
      - RowsZonemapFiltered:226.698K (226698)
      - 短预测评估时间:2.723ms
      - 总页数:5.421K (5421)
      - 未压缩字节读取:277.05 MB
    - VectorPredEvalTime:8.114ms

    不使用倒排索引,加载 16680706 行需要 3.14 秒(FirstReadTime: 3s144ms)。然后,系统通过Predicate Evaluate进行过滤,筛选出16680705行。条件过滤过程仅需不到10ms,使得原始数据加载成为最耗时的任务。

    总而言之,倒排索引通过快速检索目标行来提高查询执行效率,从而减少不必要的数据加载。

    加速低基数文本列查询

    所以倒排索引对于高基数文本列的查询来说是一个很大的加速器,但这可能会引起一个问题:对于低基数列,太多的索引会带来过多的开销并降低查询性能吗?

    答案是:不。让我向您展示原因和方式。以下示例使用product_category作为过滤的谓词列。

    MySQL

     

    mysql> 从 amazon_reviews 中选择 COUNT(DISTINCT Product_category) ;
    +----------------------------------+
    |计数(不同的产品类别)|
    +----------------------------------+
    | 43 | 43
    +----------------------------------+
    一组 1 行(0.57 秒)

    如图所示,product_category列只有 43 个不同的类别,使其成为典型的低基数文本列。现在,让我们为其添加倒排索引。

    SQL

     

    更改表 amazon_reviews 使用 INVERTED 添加索引 Product_category_inverted_idx(`product_category`);
    在 amazon_reviews 上构建索引product_category_inverted_idx;

    添加倒排索引后,运行以下 SQL 查询来检索“Mobile_Electronics”产品类别中评论最多的前 3 个产品。

    SQL

     

    选择
        产品ID,
        产品标题,
        AVG(star_ rating) AS 评级,
        任何(评论正文),
        任何(评论标题),
        COUNT(*) AS 计数
    从
        亚马逊评论
    在哪里
        产品类别 = '移动电子'
    通过...分组
        产品标题、产品 ID
    订购依据
        计数 DESC
    限制 10;

    使用倒排索引,查询需要1.54s完成。

    SQL

     

    +------------------------+------------------------ -------------------------------------------------- -------------------------------------------------- -------------------------------------------------- --------------------------------------+-------------------- +------------------------------------------------ -------------------------------------------------- -------------------------------------------------- -------------------------------------------------- -------------------------------------------------- -------------------------------------------------- -------------------------------------------------- -------------------------------------------------- -------------------------------------------------- ----------------------------------------------------+-------- ------------------------+--------------------+
    |产品 ID |产品标题 |评级|任何_值(评论正文)|任何值(评论标题)|计数|
    +------------+------------------------------------ -------------------------------------------------- -------------------------------------------------- -------------------------------------------------- --------------+--------------------+-------------- -------------------------------------------------- -------------------------------------------------- -------------------------------------------------- -------------------------------------------------- -------------------------------------------------- -------------------------------------------------- -------------------------------------------------- -------------------------------------------------- -------------------------------------------------- --------------------------+------------------------ ----------+--------+
    | B00J46XO9U | iXCC Lightning 数据线 3 英尺,iPhone 充电器,适用于 iPhone X、8、8 Plus、7、7 Plus、6s、6s Plus、6、6 Plus、SE 5s 5c 5、iPad Air 2 Pro、iPad mini 2 3 4、iPad 4th Gen【苹果MFi认证】(黑白)| 4.3766233766233764 |很棒的电缆并且运行良好。与 Apple 数据线完全相同。我会向任何想要省钱并寻求优质电缆的人推荐此产品。 |苹果认证的Lightning数据线| 1078 | 1078
    | B004911E9M |适用于 iPhone 4、3GS 和 iPod 的壁式交流充电器 USB 同步数据线 | 2.4281805745554035 |对我来说这完全是浪费钱,因为我需要将它用于 iPhone 4。插头只能倒置插入,因此根本无法使用。 |不适用于 iPhone 4! | 731 | 731
    | B002D4IHYM |新 Trent Easypak 7000mAh 便携式三 USB 端口外部电池充电器/电源组,适用于智能手机、平板电脑等(带内置 USB 线)| 4.5216095380029806 |我根据阅读的评论购买了该产品,我很高兴我这么做了。我在收到产品后确实遇到了对 itouch 充电的问题,但我给公司发了电子邮件,他们立即纠正了问题。非常好的客户服务,非常及时。产品本身非常好。它可以非常快速地为我耗电的 itouch 充电,而且 imax 电池的电量可以持续很长时间。总而言之,这是一次非常好的购买,我会推荐给所有拥有 itouch 的人。 |伟大的产品和公司| 671 | 671
    +------------+------------------------------------ -------------------------------------------------- -------------------------------------------------- -------------------------------------------------- --------------+--------------------+-------------- -------------------------------------------------- -------------------------------------------------- -------------------------------------------------- -------------------------------------------------- -------------------------------------------------- -------------------------------------------------- -------------------------------------------------- -------------------------------------------------- -------------------------------------------------- --------------------------+------------------------ ----------+--------+
    一组 3 行(1.54 秒)

    综上所述,倒排索引可以为低基数列的查询带来 15% 的加速。所以它不仅无害,而且有利于低基数数据过滤。

    此外,Apache Doris 对低基数列采用有效的字典编码和压缩。它还利用内置索引(如 ZoneMap)进行过滤。因此,即使没有倒排索引,它也能提供理想的查询性能。

    结论

    Apache Doris 中的倒排索引根据谓词列(SQL 查询中的 WHERE 子句)优化数据过滤。它减少了不必要的数据扫描,显着提高了高基数列的查询速度,并保证对低基数列不会产生负面影响。它支持轻量级索引管理,包括ADD/DROP INDEX和BUILD INDEX。可以通过 enable_inverted_index_query=true/false 轻松启用或禁用它。

    倒排索引和NGram BloomFilter索引适用于不同的场景。您可以通过以下方式确定哪一个是最佳选择:

  • 非主键列查询:这些情况通常涉及值分散且命中率较低的情况。 倒排索引可以与 Doris 中的内置智能索引结合使用,以加速这些查询。它对标量数据类型(包括字符、数字和日期时间)具有完善的支持。
  • 短文本搜索:如果数据集包含高度多样化的短文本,NGram BloomFilter将是模糊搜索的有效选择短文本匹配 (LIKE)。如果短文本非常相似(有很多相同的内容),倒排索引会更有效,因为它可以确保更小的字典和更快的行号检索。
  • 长文本搜索:倒排索引是长文本的更好选择。与野蛮的字符串匹配相比,它大大减少了CPU资源消耗。
  • 倒排索引在Apache Doris中已经上线近一年了,经受住了众多用户在生产环境中海量数据的考验。在 Apache Doris 的未来版本中,关于倒排索引,我们计划添加对以下内容的支持:

  • 自定义标记化:提供用户定义的标记器以适应不同的用例。
  • 更多数据类型:用户将能够为复杂数据类型(包括数组和映射)创建倒排索引。
  • 如果您在 Apache Doris 中尝试时遇到任何问题或想了解更多详细信息,请加入我们的 Slack 社区并与我们交谈!

    Comments are closed.