当前位置: 首页 > news >正文

从建表语句带你学习doris_表索引

1、doris建表概述

1.1、doris建表模板

CREATE [EXTERNAL] TABLE [IF NOT EXISTS] [DATABASE.]table_name
(column_definition1[,column_deinition2,......][,index_definition1,[,index_definition2,]]
)
[ENGINE = [olap|mysql|broker|hive]]
[key_desc]
[COMMENT "table comment"];
[partition_desc]
[distribute_desc]
[rollup_index]
[PROPERTIES("key"="value",...)]
[BROKER PROPERTIES("key"="value",...)];

1.2、doris建表结构

doris建表包含以下部分:

  • 内外部表定义
  • 数据列定义
  • 索引字段定义
  • 数据模型定义
  • 执行引擎定义
  • 数据分区定义
  • 数据分桶定义
  • 表属性定义
  • broker属性定义

本篇博客我们来学习索引字段部分,索引字段对于提升表的查询性能具有重要的意义,本篇文章我们将介绍表索引作用、表索引类型、表索引基本原理、表索引实践案例四部分内容

2、doris建表剖析_索引介绍

        索引是所有数据库系统提高查询性能的一个重要手段,简单的说其作用相当于我们查询汉语词典的目录,通过部首或者拼音快速帮助我们定位到某个汉字。索引通过一定的组织格式能够快速定位到数据表中的数据。doris目前支持两种索引:

  • 内建的智能索引,包括前缀索引和 ZoneMap 索引。
  • 用户手动创建的二级索引,包括 倒排索引、 bloomfilter索引 和 ngram bloomfilter索引 。

3、前缀索引详解

3.1、前缀索引背景介绍

        不同于传统的数据库设计,Doris 不支持在任意列上创建索引。Doris 这类 MPP 架构的 OLAP 数据库,通常都是通过提高并发,来处理大量数据的。本质上Doris 的数据存储在类似 SSTable(Sorted String Table)的数据结构中。该结构是一种有序的数据结构,可以按照指定的列进行排序存储。在这种数据结构上,以排序列作为条件进行查找,会非常的高效。在 Aggregate、Unique 和 Duplicate 三种数据模型中。底层的数据存储,是按照各自建表语句中,AGGREGATE KEY、UNIQUE KEY 和 DUPLICATE KEY 中指定的列进行排序存储的。前缀索引,即在排序的基础上,实现的一种根据给定前缀列,快速查询数据的索引方式。

3.2、前缀索引案例讲解

        我们将一行数据的前 36 个字节 作为这行数据的前缀索引。当遇到 VARCHAR 类型时,前缀索引会直接截断。我们举例说明:

  1. 以下表结构的前缀索引为 user_id(8 Bytes) + age(4 Bytes) + message(prefix 24 Bytes)

    ColumnNameType
    user_idBIGINT
    ageINT
    messageVARCHAR(100)
    max_dwell_timeDATETIME
    min_dwell_timeDATETIME
  2. 以下表结构的前缀索引为 user_name(20 Bytes)。即使没有达到 36 个字节,因为遇到 VARCHAR,所以直接截断,不再往后继续。

    ColumnNameType
    user_nameVARCHAR(20)
    ageINT
    messageVARCHAR(100)
    max_dwell_timeDATETIME
    min_dwell_timeDATETIME

当我们的查询条件,是前缀索引的前缀时,可以极大的加快查询速度。比如在第一个例子中,我们执行如下查询:

--查询方式1
SELECT * FROM table WHERE user_id=1829239 and age=20;--查询方式2
SELECT * FROM table WHERE age=20;

查找速度方面,查询方式1会远高于查询方式2,所以在建表时,正确的选择列顺序,能够极大地提高查询效率

3.3、前缀索引调整方法​

        由于建表时已指定列顺序,所以一个表只有一种前缀索引。这对于使用其他不能命中前缀索引的列作为条件进行的查询来说,效率上可能无法满足需求。因此,我们可以通过创建 ROLLUP 来人为的调整列顺序。详情可参考 ROLLUP。

4、zonemap索引详解

        ZoneMap 索引是在列存格式上,对每一列自动维护的索引信息,包括 Min/Max,Null 值个数等等。这种索引对用户透明,我们在日常并不直接使用。

5、倒排索引详解

        从2.0.0版本开始,Doris支持倒排索引,可以用来进行文本类型的全文检索普通数值日期类型的等值范围查询,快速从海量数据中过滤出满足条件的行。接下来我们主要介绍倒排索引实现原理、如何倒排索引的创建、删除、查询等使用方式。​

5.1、 原理介绍​

        倒排索引是信息检索领域常用的索引技术,其本质是将文本分割成一个个词,构建 词 -> 文档编号 的索引,可以快速查找一个词在哪些文档出现。在Doris的倒排索引实现中,table的一行对应一个文档、一列对应文档中的一个字段,因此利用倒排索引可以根据关键词快速定位包含它的行,达到WHERE子句加速的目的。且与Doris中其他索引不同的是,在存储层倒排索引使用独立的文件,跟segment文件有逻辑对应关系、但存储的文件相互独立。这样的好处是可以做到创建、删除索引不用重写tablet和segment文件,大幅降低处理开销。

5.2、功能介绍​

Doris倒排索引的功能简要介绍如下:

  • 增加了字符串类型的全文检索
    • 支持字符串全文检索,包括同时匹配多个关键字MATCH_ALL、匹配任意一个关键字MATCH_ANY
    • 支持短语查询 MATCH_PHRASE
    • 支持短语+前缀 MATCH_PHRASE_PREFIX
    • 支持正则查询 MATCH_REGEXP
    • 支持字符串数组类型的全文检索
    • 支持英文、中文以及Unicode多语言分词
  • 加速普通等值、范围查询,覆盖bitmap索引的功能,可代替bitmap索引
    • 支持字符串、数值、日期时间类型的 =, !=, >, >=, <, <= 快速过滤
    • 支持字符串、数字、日期时间数组类型的 =, !=, >, >=, <, <=
  • 支持完善的逻辑组合
    • 新增索引对OR NOT逻辑的下推
    • 支持多个条件的任意AND OR NOT组合
  • 灵活、快速的索引管理
    • 支持在创建表上定义倒排索引
    • 支持在已有的表上增加倒排索引,而且支持增量构建倒排索引,无需重写表中的已有数据
    • 支持删除已有表上的倒排索引,无需重写表中的已有数据

5.3、倒排索引属性介绍

5.3.1、分词器属性

parser指定分词器(默认不指定代表不分词)

  • english是英文分词,适合被索引列是英文的情况,用空格和标点符号分词,性能高
  • chinese是中文分词,适合被索引列主要是中文的情况,性能比english分词低
  • unicode是多语言混合类型分词,适用于中英文混合、多语言混合的情况。它能够对邮箱前缀和后缀、IP地址以及字符数字混合进行分词,并且可以对中文按字符分词。

​5.3.2、分词模式属性

目前parser = chinese时支持如下几种模式(默认coarse_grained):

  • fine_grained:细粒度模式,倾向于分出比较短的词,比如 '武汉市长江大桥' 会分成 '武汉', '武汉市', '市长', '长江', '长江大桥', '大桥' 6个词
  • coarse_grained:粗粒度模式,倾向于分出比较长的词,,比如 '武汉市长江大桥' 会分成 '武汉市' '长江大桥' 2个词

5.3.3、char_filter属性

  • 功能主要在分词前对字符串提前处理
  • char_filter_type:指定使用不同功能的char_filter(目前仅支持char_replace)
    • char_replace 将pattern中每个char替换为一个replacement中的char
      • char_filter_pattern:需要被替换掉的字符数组
      • char_filter_replacement:替换后的字符数组,可以不用配置,默认为一个空格字符

5.3.4、lower_case属性

  • lower_case: 是否将分词进行小写转换,从而在匹配的时候实现忽略大小写
    • true: 转换小写
    • false:不转换小写

5.3.5、ignore_above属性

  • ignore_above:控制字符串是否建索引。
    • 长度超过 ignore_above 设置的字符串(默认256字节)不会被索引。对于字符串数组,ignore_above 将分别应用于每个数组元素,长度超过 ignore_above 的字符串元素将不被索引。

5.3.6、support_phrase属性

用于指定索引是否支持MATCH_PHRASE短语查询加速

  • true为支持,但是索引需要更多的存储空间
  • false为不支持,更省存储空间,可以用MATCH_ALL查询多个关键字
  • 默认false
CREATE TABLE table_name
(columns_difinition,INDEX idx_name1(column_name1) USING INVERTED [PROPERTIES("parser" = "english|unicode|chinese")] [COMMENT 'your comment']INDEX idx_name2(column_name2) USING INVERTED [PROPERTIES("parser" = "english|unicode|chinese")] [COMMENT 'your comment']INDEX idx_name3(column_name3) USING INVERTED [PROPERTIES("parser" = "chinese", "parser_mode" = "fine_grained|coarse_grained")] [COMMENT 'your comment']INDEX idx_name4(column_name4) USING INVERTED [PROPERTIES("parser" = "english|unicode|chinese", "support_phrase" = "true|false")] [COMMENT 'your comment']INDEX idx_name5(column_name4) USING INVERTED [PROPERTIES("char_filter_type" = "char_replace", "char_filter_pattern" = "._"), "char_filter_replacement" = " "] [COMMENT 'your comment']INDEX idx_name5(column_name4) USING INVERTED [PROPERTIES("char_filter_type" = "char_replace", "char_filter_pattern" = "._")] [COMMENT 'your comment']
)
table_properties;

5.4、使用限制

倒排索引在不同数据模型中有不同的使用限制:

  • Aggregate 模型:只能为 Key 列建立倒排索引。
  • Unique 模型:需要开启 merge on write 特性,开启后,可以为任意列建立倒排索引。
  • Duplicate 模型:可以为任意列建立倒排索引。
  • 已有表增加倒排索引

2.0-beta版本之前:

-- 语法1
CREATE INDEX idx_name ON table_name(column_name) USING INVERTED [PROPERTIES("parser" = "english|unicode|chinese")] [COMMENT 'your comment'];
-- 语法2
ALTER TABLE table_name ADD INDEX idx_name(column_name) USING INVERTED [PROPERTIES("parser" = "english|unicode|chinese")] [COMMENT 'your comment'];

2.0-beta版本(含2.0-beta)之后:

上述create/add index操作只对增量数据生成倒排索引,增加了BUILD INDEX的语法用于对存量数据加倒排索引:

-- 语法1,默认给全表的存量数据加上倒排索引
BUILD INDEX index_name ON table_name;
-- 语法2,可指定partition,可指定一个或多个
BUILD INDEX index_name ON table_name PARTITIONS(partition_name1, partition_name2);

5.5、倒排索引操作语法介绍

倒排索引定义的语法为:index index_name(column_name) using inverted [properties];

using inverted用于声明索引类型为倒排索引;properties用于声明倒排索引的额外属性,其属性主要包含分词器、分词模式、是否支持MATCH_PHRASE短语查询加速

5.5.1、创建倒排索引

5.5.2、删除倒排索引

-- 语法1
DROP INDEX idx_name ON table_name;-- 语法2
ALTER TABLE table_name DROP INDEX idx_name;

5.5.3、修改倒排索引

5.5.4、查询倒排索引

SHOW BUILD INDEX [FROM db_name];
-- 示例1,查看所有的BUILD INDEX任务进展
SHOW BUILD INDEX;
-- 示例2,查看指定table的BUILD INDEX任务进展
SHOW BUILD INDEX where TableName = "table1";

取消 BUILD INDEX, 可通过以下语句进行

CANCEL BUILD INDEX ON table_name;
CANCEL BUILD INDEX ON table_name (job_id1,jobid_2,...);

  • 利用倒排索引加速查询
-- 1. 全文检索关键词匹配,通过MATCH_ANY MATCH_ALL完成
SELECT * FROM table_name WHERE column_name MATCH_ANY | MATCH_ALL 'keyword1 ...';-- 1.1 logmsg中包含keyword1的行
SELECT * FROM table_name WHERE logmsg MATCH_ANY 'keyword1';-- 1.2 logmsg中包含keyword1或者keyword2的行,后面还可以添加多个keyword
SELECT * FROM table_name WHERE logmsg MATCH_ANY 'keyword1 keyword2';-- 1.3 logmsg中同时包含keyword1和keyword2的行,后面还可以添加多个keyword
SELECT * FROM table_name WHERE logmsg MATCH_ALL 'keyword1 keyword2';-- 1.4 logmsg中同时包含keyword1和keyword2的行,并且按照keyword1在前,keyword2在后的顺序
SELECT * FROM table_name WHERE logmsg MATCH_PHRASE 'keyword1 keyword2';-- 1.5 在保持词顺序的前提下,对最后一个词keyword2做前缀匹配,默认找50个前缀词(session变量inverted_index_max_expansions控制)
SELECT * FROM table_name WHERE logmsg MATCH_PHRASE_PREFIX 'keyword1 keyword2';-- 1.6 如果只填一个词会退化为前缀查询,默认找50个前缀词(session变量inverted_index_max_expansions控制)
SELECT * FROM table_name WHERE logmsg MATCH_PHRASE_PREFIX 'keyword1';-- 1.7 对分词后的词进行正则匹配,默认匹配50个(session变量inverted_index_max_expansions控制)
SELECT * FROM table_name WHERE logmsg MATCH_REGEXP 'key*';-- 2. 普通等值、范围、IN、NOT IN,正常的SQL语句即可,例如
SELECT * FROM table_name WHERE id = 123;
SELECT * FROM table_name WHERE ts > '2023-01-01 00:00:00';
SELECT * FROM table_name WHERE op_type IN ('add', 'delete');

  • 分词函数

如果想检查分词实际效果或者对一段文本进行分词的话,可以使用tokenize函数

mysql> SELECT TOKENIZE('武汉长江大桥','"parser"="chinese","parser_mode"="fine_grained"');
+-----------------------------------------------------------------------------------+
| tokenize('武汉长江大桥', '"parser"="chinese","parser_mode"="fine_grained"')       |
+-----------------------------------------------------------------------------------+
| ["武汉", "武汉长江大桥", "长江", "长江大桥", "大桥"]                              |
+-----------------------------------------------------------------------------------+
1 row in set (0.02 sec)mysql> SELECT TOKENIZE('武汉市长江大桥','"parser"="chinese","parser_mode"="fine_grained"');
+--------------------------------------------------------------------------------------+
| tokenize('武汉市长江大桥', '"parser"="chinese","parser_mode"="fine_grained"')        |
+--------------------------------------------------------------------------------------+
| ["武汉", "武汉市", "市长", "长江", "长江大桥", "大桥"]                               |
+--------------------------------------------------------------------------------------+
1 row in set (0.02 sec)mysql> SELECT TOKENIZE('武汉市长江大桥','"parser"="chinese","parser_mode"="coarse_grained"');
+----------------------------------------------------------------------------------------+
| tokenize('武汉市长江大桥', '"parser"="chinese","parser_mode"="coarse_grained"')        |
+----------------------------------------------------------------------------------------+
| ["武汉市", "长江大桥"]                                                                 |
+----------------------------------------------------------------------------------------+
1 row in set (0.02 sec)mysql> SELECT TOKENIZE('I love CHINA','"parser"="english"');
+------------------------------------------------+
| tokenize('I love CHINA', '"parser"="english"') |
+------------------------------------------------+
| ["i", "love", "china"]                         |
+------------------------------------------------+
1 row in set (0.02 sec)mysql> SELECT TOKENIZE('I love CHINA 我爱我的祖国','"parser"="unicode"');
+-------------------------------------------------------------------+
| tokenize('I love CHINA 我爱我的祖国', '"parser"="unicode"')       |
+-------------------------------------------------------------------+
| ["i", "love", "china", "我", "爱", "我", "的", "祖", "国"]        |
+-------------------------------------------------------------------+
1 row in set (0.02 sec)

6、倒排索引实践案例

用hackernews 100万条数据展示倒排索引的创建、全文检索、普通查询,包括跟无索引的查询性能进行简单对比。

建表​

CREATE DATABASE test_inverted_index;USE test_inverted_index;-- 创建表的同时创建了comment的倒排索引idx_comment
--   USING INVERTED 指定索引类型是倒排索引
--   PROPERTIES("parser" = "english") 指定采用english分词,还支持"chinese"中文分词和"unicode"中英文多语言混合分词,如果不指定"parser"参数表示不分词
CREATE TABLE hackernews_1m
(`id` BIGINT,`deleted` TINYINT,`type` String,`author` String,`timestamp` DateTimeV2,`comment` String,`dead` TINYINT,`parent` BIGINT,`poll` BIGINT,`children` Array<BIGINT>,`url` String,`score` INT,`title` String,`parts` Array<INT>,`descendants` INT,INDEX idx_comment (`comment`) USING INVERTED PROPERTIES("parser" = "english") COMMENT 'inverted index for comment'
)
DUPLICATE KEY(`id`)
DISTRIBUTED BY HASH(`id`) BUCKETS 10
PROPERTIES ("replication_num" = "1");

导入数据​

  • 通过stream load导入数据
wget https://doris-build-1308700295.cos.ap-beijing.myqcloud.com/regression/index/hacknernews_1m.csv.gzcurl --location-trusted -u root: -H "compress_type:gz" -T hacknernews_1m.csv.gz  http://127.0.0.1:8030/api/test_inverted_index/hackernews_1m/_stream_load
{"TxnId": 2,"Label": "a8a3e802-2329-49e8-912b-04c800a461a6","TwoPhaseCommit": "false","Status": "Success","Message": "OK","NumberTotalRows": 1000000,"NumberLoadedRows": 1000000,"NumberFilteredRows": 0,"NumberUnselectedRows": 0,"LoadBytes": 130618406,"LoadTimeMs": 8988,"BeginTxnTimeMs": 23,"StreamLoadPutTimeMs": 113,"ReadDataTimeMs": 4788,"WriteDataTimeMs": 8811,"CommitAndPublishTimeMs": 38
}

  • SQL运行count()确认导入数据成功
mysql> SELECT count() FROM hackernews_1m;
+---------+
| count() |
+---------+
| 1000000 |
+---------+
1 row in set (0.02 sec)

查询​

全文检索​
  • 用LIKE匹配计算comment中含有'OLAP'的行数,耗时0.18s
mysql> SELECT count() FROM hackernews_1m WHERE comment LIKE '%OLAP%';
+---------+
| count() |
+---------+
|      34 |
+---------+
1 row in set (0.18 sec)

  • 用基于倒排索引的全文检索MATCH_ANY计算comment中含有'OLAP'的行数,耗时0.02s,加速9倍,在更大的数据集上效果会更加明显
    • 这里结果条数的差异,是因为倒排索引对comment分词后,还会对词进行进行统一成小写等归一化处理,因此MATCH_ANY比LIKE的结果多一些
mysql> SELECT count() FROM hackernews_1m WHERE comment MATCH_ANY 'OLAP';
+---------+
| count() |
+---------+
|      35 |
+---------+
1 row in set (0.02 sec)

  • 同样的对比统计'OLTP'出现次数的性能,0.07s vs 0.01s,由于缓存的原因LIKE和MATCH_ANY都有提升,倒排索引仍然有7倍加速
mysql> SELECT count() FROM hackernews_1m WHERE comment LIKE '%OLTP%';
+---------+
| count() |
+---------+
|      48 |
+---------+
1 row in set (0.07 sec)mysql> SELECT count() FROM hackernews_1m WHERE comment MATCH_ANY 'OLTP';
+---------+
| count() |
+---------+
|      51 |
+---------+
1 row in set (0.01 sec)

  • 同时出现'OLAP'和'OLTP'两个词,0.13s vs 0.01s,13倍加速
    • 要求多个词同时出现时(AND关系)使用 MATCH_ALL 'keyword1 keyword2 ...'
mysql> SELECT count() FROM hackernews_1m WHERE comment LIKE '%OLAP%' AND comment LIKE '%OLTP%';
+---------+
| count() |
+---------+
|      14 |
+---------+
1 row in set (0.13 sec)mysql> SELECT count() FROM hackernews_1m WHERE comment MATCH_ALL 'OLAP OLTP';
+---------+
| count() |
+---------+
|      15 |
+---------+
1 row in set (0.01 sec)

  • 任意出现'OLAP'和'OLTP'其中一个词,0.12s vs 0.01s,12倍加速
    • 只要求多个词任意一个或多个出现时(OR关系)使用 MATCH_ANY 'keyword1 keyword2 ...'
mysql> SELECT count() FROM hackernews_1m WHERE comment LIKE '%OLAP%' OR comment LIKE '%OLTP%';
+---------+
| count() |
+---------+
|      68 |
+---------+
1 row in set (0.12 sec)mysql> SELECT count() FROM hackernews_1m WHERE comment MATCH_ANY 'OLAP OLTP';
+---------+
| count() |
+---------+
|      71 |
+---------+
1 row in set (0.01 sec)

普通等值、范围查询​
  • DataTime类型的列范围查询
mysql> SELECT count() FROM hackernews_1m WHERE timestamp > '2007-08-23 04:17:00';
+---------+
| count() |
+---------+
|  999081 |
+---------+
1 row in set (0.03 sec)

  • 为timestamp列增加一个倒排索引
-- 对于日期时间类型USING INVERTED,不用指定分词
-- CREATE INDEX 是第一种建索引的语法,另外一种在后面展示
mysql> CREATE INDEX idx_timestamp ON hackernews_1m(timestamp) USING INVERTED;
Query OK, 0 rows affected (0.03 sec)

2.0-beta(含2.0-beta)后,需要再执行BUILD INDEX才能给存量数据加上倒排索引:

mysql> BUILD INDEX idx_timestamp ON hackernews_1m;
Query OK, 0 rows affected (0.01 sec)

  • 查看索引创建进度,通过FinishTime和CreateTime的差值,可以看到100万条数据对timestamp列建倒排索引只用了1s
mysql> SHOW ALTER TABLE COLUMN;
+-------+---------------+-------------------------+-------------------------+---------------+---------+---------------+---------------+---------------+----------+------+----------+---------+
| JobId | TableName     | CreateTime              | FinishTime              | IndexName     | IndexId | OriginIndexId | SchemaVersion | TransactionId | State    | Msg  | Progress | Timeout |
+-------+---------------+-------------------------+-------------------------+---------------+---------+---------------+---------------+---------------+----------+------+----------+---------+
| 10030 | hackernews_1m | 2023-02-10 19:44:12.929 | 2023-02-10 19:44:13.938 | hackernews_1m | 10031   | 10008         | 1:1994690496  | 3             | FINISHED |      | NULL     | 2592000 |
+-------+---------------+-------------------------+-------------------------+---------------+---------+---------------+---------------+---------------+----------+------+----------+---------+
1 row in set (0.00 sec)

2.0-beta(含2.0-beta)后,可通过show builde index来查看存量数据创建索引进展:

-- 若table没有分区,PartitionName默认就是TableName
mysql> SHOW BUILD INDEX;
+-------+---------------+---------------+----------------------------------------------------------+-------------------------+-------------------------+---------------+----------+------+----------+
| JobId | TableName     | PartitionName | AlterInvertedIndexes                                     | CreateTime              | FinishTime              | TransactionId | State    | Msg  | Progress |
+-------+---------------+---------------+----------------------------------------------------------+-------------------------+-------------------------+---------------+----------+------+----------+
| 10191 | hackernews_1m | hackernews_1m | [ADD INDEX idx_timestamp (`timestamp`) USING INVERTED],  | 2023-06-26 15:32:33.894 | 2023-06-26 15:32:34.847 | 3             | FINISHED |      | NULL     |
+-------+---------------+---------------+----------------------------------------------------------+-------------------------+-------------------------+---------------+----------+------+----------+
1 row in set (0.04 sec)

  • 索引创建后,范围查询用同样的查询方式,Doris会自动识别索引进行优化,但是这里由于数据量小性能差别不大
mysql> SELECT count() FROM hackernews_1m WHERE timestamp > '2007-08-23 04:17:00';
+---------+
| count() |
+---------+
|  999081 |
+---------+
1 row in set (0.01 sec)

  • 在数值类型的列parent进行类似timestamp的操作,这里查询使用等值匹配
mysql> SELECT count() FROM hackernews_1m WHERE parent = 11189;
+---------+
| count() |
+---------+
|       2 |
+---------+
1 row in set (0.01 sec)-- 对于数值类型USING INVERTED,不用指定分词
-- ALTER TABLE t ADD INDEX 是第二种建索引的语法
mysql> ALTER TABLE hackernews_1m ADD INDEX idx_parent(parent) USING INVERTED;
Query OK, 0 rows affected (0.01 sec)-- 2.0-beta(含2.0-beta)后,需要再执行BUILD INDEX才能给存量数据加上倒排索引:
mysql> BUILD INDEX idx_parent ON hackernews_1m;
Query OK, 0 rows affected (0.01 sec)mysql> SHOW ALTER TABLE COLUMN;
+-------+---------------+-------------------------+-------------------------+---------------+---------+---------------+---------------+---------------+----------+------+----------+---------+
| JobId | TableName     | CreateTime              | FinishTime              | IndexName     | IndexId | OriginIndexId | SchemaVersion | TransactionId | State    | Msg  | Progress | Timeout |
+-------+---------------+-------------------------+-------------------------+---------------+---------+---------------+---------------+---------------+----------+------+----------+---------+
| 10030 | hackernews_1m | 2023-02-10 19:44:12.929 | 2023-02-10 19:44:13.938 | hackernews_1m | 10031   | 10008         | 1:1994690496  | 3             | FINISHED |      | NULL     | 2592000 |
| 10053 | hackernews_1m | 2023-02-10 19:49:32.893 | 2023-02-10 19:49:33.982 | hackernews_1m | 10054   | 10008         | 1:378856428   | 4             | FINISHED |      | NULL     | 2592000 |
+-------+---------------+-------------------------+-------------------------+---------------+---------+---------------+---------------+---------------+----------+------+----------+---------+mysql> SHOW BUILD INDEX;
+-------+---------------+---------------+----------------------------------------------------+-------------------------+-------------------------+---------------+----------+------+----------+
| JobId | TableName     | PartitionName | AlterInvertedIndexes                               | CreateTime              | FinishTime              | TransactionId | State    | Msg  | Progress |
+-------+---------------+---------------+----------------------------------------------------+-------------------------+-------------------------+---------------+----------+------+----------+
| 11005 | hackernews_1m | hackernews_1m | [ADD INDEX idx_parent (`parent`) USING INVERTED],  | 2023-06-26 16:25:10.167 | 2023-06-26 16:25:10.838 | 1002          | FINISHED |      | NULL     |
+-------+---------------+---------------+----------------------------------------------------+-------------------------+-------------------------+---------------+----------+------+----------+
1 row in set (0.01 sec)mysql> SELECT count() FROM hackernews_1m WHERE parent = 11189;
+---------+
| count() |
+---------+
|       2 |
+---------+
1 row in set (0.01 sec)

  • 对字符串类型的author建立不分词的倒排索引,等值查询也可以利用索引加速
mysql> SELECT count() FROM hackernews_1m WHERE author = 'faster';
+---------+
| count() |
+---------+
|      20 |
+---------+
1 row in set (0.03 sec)-- 这里只用了USING INVERTED,不对author分词,整个当做一个词处理
mysql> ALTER TABLE hackernews_1m ADD INDEX idx_author(author) USING INVERTED;
Query OK, 0 rows affected (0.01 sec)-- 2.0-beta(含2.0-beta)后,需要再执行BUILD INDEX才能给存量数据加上倒排索引:
mysql> BUILD INDEX idx_author ON hackernews_1m;
Query OK, 0 rows affected (0.01 sec)-- 100万条author数据增量建索引仅消耗1.5s
mysql> SHOW ALTER TABLE COLUMN;
+-------+---------------+-------------------------+-------------------------+---------------+---------+---------------+---------------+---------------+----------+------+----------+---------+
| JobId | TableName     | CreateTime              | FinishTime              | IndexName     | IndexId | OriginIndexId | SchemaVersion | TransactionId | State    | Msg  | Progress | Timeout |
+-------+---------------+-------------------------+-------------------------+---------------+---------+---------------+---------------+---------------+----------+------+----------+---------+
| 10030 | hackernews_1m | 2023-02-10 19:44:12.929 | 2023-02-10 19:44:13.938 | hackernews_1m | 10031   | 10008         | 1:1994690496  | 3             | FINISHED |      | NULL     | 2592000 |
| 10053 | hackernews_1m | 2023-02-10 19:49:32.893 | 2023-02-10 19:49:33.982 | hackernews_1m | 10054   | 10008         | 1:378856428   | 4             | FINISHED |      | NULL     | 2592000 |
| 10076 | hackernews_1m | 2023-02-10 19:54:20.046 | 2023-02-10 19:54:21.521 | hackernews_1m | 10077   | 10008         | 1:1335127701  | 5             | FINISHED |      | NULL     | 2592000 |
+-------+---------------+-------------------------+-------------------------+---------------+---------+---------------+---------------+---------------+----------+------+----------+---------+mysql> SHOW BUILD INDEX order by CreateTime desc limit 1;
+-------+---------------+---------------+----------------------------------------------------+-------------------------+-------------------------+---------------+----------+------+----------+
| JobId | TableName     | PartitionName | AlterInvertedIndexes                               | CreateTime              | FinishTime              | TransactionId | State    | Msg  | Progress |
+-------+---------------+---------------+----------------------------------------------------+-------------------------+-------------------------+---------------+----------+------+----------+
| 13006 | hackernews_1m | hackernews_1m | [ADD INDEX idx_author (`author`) USING INVERTED],  | 2023-06-26 17:23:02.610 | 2023-06-26 17:23:03.755 | 3004          | FINISHED |      | NULL     |
+-------+---------------+---------------+----------------------------------------------------+-------------------------+-------------------------+---------------+----------+------+----------+
1 row in set (0.01 sec)-- 创建索引后,字符串等值匹配也有明显加速
mysql> SELECT count() FROM hackernews_1m WHERE author = 'faster';
+---------+
| count() |
+---------+
|      20 |
+---------+

6、bloomfilter索引详解

BloomFilter是由Bloom在1970年提出的一种多哈希函数映射的快速查找算法。通常应用在一些需要快速判断某个元素是否属于集合,但是并不严格要求100%正确的场合,BloomFilter有以下特点:

  • 空间效率高的概率型数据结构,用来检查一个元素是否在一个集合中。
  • 对于一个元素检测是否存在的调用,BloomFilter会告诉调用者两个结果之一:可能存在或者一定不存在。
  • 缺点是存在误判,告诉你可能存在,不一定真实存在。

布隆过滤器实际上是由一个超长的二进制位数组和一系列的哈希函数组成。二进制位数组初始全部为0,当给定一个待查询的元素时,这个元素会被一系列哈希函数计算映射出一系列的值,所有的值在位数组的偏移量处置为1。

下图所示出一个 m=18, k=3 (m是该Bit数组的大小,k是Hash函数的个数)的Bloom Filter示例。集合中的 x、y、z 三个元素通过 3 个不同的哈希函数散列到位数组中。当查询元素w时,通过Hash函数计算之后因为有一个比特为0,因此w不在该集合中。

Bloom_filter.svg

那么怎么判断某个元素是否在集合中呢?同样是这个元素经过哈希函数计算后得到所有的偏移位置,若这些位置全都为1,则判断这个元素在这个集合中,若有一个不为1,则判断这个元素不在这个集合中。就是这么简单!

Doris BloomFilter索引及使用使用场景​

举个例子:如果要查找一个占用100字节存储空间大小的短行,一个64KB的HFile数据块应该包含(64 * 1024)/100 = 655.53 = ~700行,如果仅能在整个数据块的起始行键上建立索引,那么它是无法给你提供细粒度的索引信息的。因为要查找的行数据可能会落在该数据块的行区间上,也可能行数据没在该数据块上,也可能是表中根本就不存在该行数据,也或者是行数据在另一个HFile里,甚至在MemStore里。以上这几种情况,都会导致从磁盘读取数据块时带来额外的IO开销,也会滥用数据块的缓存,当面对一个巨大的数据集且处于高并发读时,会严重影响性能。

因此,HBase提供了布隆过滤器,它允许你对存储在每个数据块的数据做一个反向测试。当某行被请求时,通过布隆过滤器先检查该行是否不在这个数据块,布隆过滤器要么确定回答该行不在,要么回答它不知道。这就是为什么我们称它是反向测试。布隆过滤器同样也可以应用到行里的单元上,当访问某列标识符时可以先使用同样的反向测试。

但布隆过滤器也不是没有代价。存储这个额外的索引层次会占用额外的空间。布隆过滤器随着它们的索引对象数据增长而增长,所以行级布隆过滤器比列标识符级布隆过滤器占用空间要少。当空间不是问题时,它们可以帮助你榨干系统的性能潜力。 Doris的BloomFilter索引可以通过建表的时候指定,或者通过表的ALTER操作来完成。Bloom Filter本质上是一种位图结构,用于快速的判断一个给定的值是否在一个集合中。这种判断会产生小概率的误判。即如果返回false,则一定不在这个集合内。而如果范围true,则有可能在这个集合内。

BloomFilter索引也是以Block为粒度创建的。每个Block中,指定列的值作为一个集合生成一个BloomFilter索引条目,用于在查询是快速过滤不满足条件的数据。

下面我们通过实例来看看Doris怎么创建BloomFilter索引。

创建BloomFilter索引​

Doris BloomFilter索引的创建是通过在建表语句的PROPERTIES里加上"bloom_filter_columns"="k1,k2,k3",这个属性,k1,k2,k3是你要创建的BloomFilter索引的Key列名称,例如下面我们对表里的saler_id,category_id创建了BloomFilter索引。

CREATE TABLE IF NOT EXISTS sale_detail_bloom  (sale_date date NOT NULL COMMENT "销售时间",customer_id int NOT NULL COMMENT "客户编号",saler_id int NOT NULL COMMENT "销售员",sku_id int NOT NULL COMMENT "商品编号",category_id int NOT NULL COMMENT "商品分类",sale_count int NOT NULL COMMENT "销售数量",sale_price DECIMAL(12,2) NOT NULL COMMENT "单价",sale_amt DECIMAL(20,2)  COMMENT "销售总金额"
)
Duplicate  KEY(sale_date, customer_id,saler_id,sku_id,category_id)
PARTITION BY RANGE(sale_date)
(
PARTITION P_202111 VALUES [('2021-11-01'), ('2021-12-01'))
)
DISTRIBUTED BY HASH(saler_id) BUCKETS 10
PROPERTIES (
"replication_num" = "3",
"bloom_filter_columns"="saler_id,category_id",
"dynamic_partition.enable" = "true",
"dynamic_partition.time_unit" = "MONTH",
"dynamic_partition.time_zone" = "Asia/Shanghai",
"dynamic_partition.start" = "-2147483648",
"dynamic_partition.end" = "2",
"dynamic_partition.prefix" = "P_",
"dynamic_partition.replication_num" = "3",
"dynamic_partition.buckets" = "3"
);

查看BloomFilter索引​

查看我们在表上建立的BloomFilter索引是使用:

SHOW CREATE TABLE <table_name>;

删除BloomFilter索引​

删除索引即为将索引列从bloom_filter_columns属性中移除:

ALTER TABLE <db.table_name> SET ("bloom_filter_columns" = "");

修改BloomFilter索引​

修改索引即为修改表的bloom_filter_columns属性:

ALTER TABLE <db.table_name> SET ("bloom_filter_columns" = "k1,k3");

Doris BloomFilter使用场景

满足以下几个条件时可以考虑对某列建立Bloom Filter 索引:

  1. 首先BloomFilter适用于非前缀过滤。
  2. 查询会根据该列高频过滤,而且查询条件大多是 in 和 = 过滤。
  3. BloomFilter适用于高基数列。比如UserID。因为如果创建在低基数的列上,比如 “性别” 列,则每个Block几乎都会包含所有取值,导致BloomFilter索引失去意义。

Doris BloomFilter使用注意事项

  1. 不支持对Tinyint、Float、Double 类型的列建Bloom Filter索引。
  2. Bloom Filter索引只对 in 和 = 过滤查询有加速效果。
  3. 如果要查看某个查询是否命中了Bloom Filter索引,可以通过查询的Profile信息查看。

7、ngram bloomfilter索引详解

NGram BloomFilter 索引

SinceVersion 2.0.0

为了提升like的查询性能,增加了NGram BloomFilter索引。

NGram BloomFilter创建​

表创建时指定:

CREATE TABLE `table3` (`siteid` int(11) NULL DEFAULT "10" COMMENT "",`citycode` smallint(6) NULL COMMENT "",`username` varchar(32) NULL DEFAULT "" COMMENT "",INDEX idx_ngrambf (`username`) USING NGRAM_BF PROPERTIES("gram_size"="3", "bf_size"="256") COMMENT 'username ngram_bf index'
) ENGINE=OLAP
AGGREGATE KEY(`siteid`, `citycode`, `username`) COMMENT "OLAP"
DISTRIBUTED BY HASH(`siteid`) BUCKETS 10
PROPERTIES (
"replication_num" = "1"
);-- PROPERTIES("gram_size"="3", "bf_size"="256"),分别表示gram的个数和bloom filter的字节数。
-- gram的个数跟实际查询场景相关,通常设置为大部分查询字符串的长度,bloom filter字节数,可以通过测试得出,通常越大过滤效果越好,可以从256开始进行验证测试看看效果。当然字节数越大也会带来索引存储、内存cost上升。
-- 如果数据基数比较高,字节数可以不用设置过大,如果基数不是很高,可以通过增加字节数来提升过滤效果。

查看NGram BloomFilter索引​

查看我们在表上建立的NGram BloomFilter索引是使用:

show index from example_db.table3;

删除NGram BloomFilter索引​

alter table example_db.table3 drop index idx_ngrambf;

修改NGram BloomFilter索引​

为已有列新增NGram BloomFilter索引:

alter table example_db.table3 add index idx_ngrambf(username) using NGRAM_BF PROPERTIES("gram_size"="2", "bf_size"="512")comment 'username ngram_bf index' 

Doris NGram BloomFilter使用注意事项

  1. NGram BloomFilter只支持字符串列
  2. NGram BloomFilter索引和BloomFilter索引为互斥关系,即同一个列只能设置两者中的一个
  3. NGram大小和BloomFilter的字节数,可以根据实际情况调优,如果NGram比较小,可以适当增加BloomFilter大小
  4. 如果要查看某个查询是否命中了NGram Bloom Filter索引,可以通过查询的Profile信息查看

       

相关文章:

从建表语句带你学习doris_表索引

1、doris建表概述 1.1、doris建表模板 CREATE [EXTERNAL] TABLE [IF NOT EXISTS] [DATABASE.]table_name (column_definition1[,column_deinition2,......][,index_definition1,[,index_definition2,]] ) [ENGINE [olap|mysql|broker|hive]] [key_desc] [COMMENT "tabl…...

Linux CentOS 安装 MySQL 服务教程

Linux CentOS 安装 MySQL 服务教程 1. 查看系统和GNU C库(glibc)版本信息 1.1 查询机器 glibc 版本信息 glibc&#xff0c;全名GNU C Library&#xff0c;是大多数Linux发行版中使用的C库&#xff0c;为系统和应用程序提供核心的API接口。在Linux系统中&#xff0c;特别是在…...

MSSQL 命令行操作说明 sql server 2022 命令行下进行配置管理

说明&#xff1a;本文的内容是因为我在导入Access2019的 *.accdb 格式的数据时&#xff0c;总是出错的背景下&#xff0c;不得已搜索和整理了一下&#xff0c;如何用命令行进行sql server 数据库和用户管理的方法&#xff0c;作为从Access2019 直接导出数据到sql server 数据库…...

【系统分析师】系统安全分析与设计

文章目录 1、安全基础技术1.1 密码相关1.1.1对称加密1.1.2非对称加密1.1.3信息摘要1.1.4数字签名1.1.5数字信封 1.2 PKI公钥体系 2、信息系统安全2.1 保障层次2.2 网络安全2.2.1WIFI2.2.2 网络威胁与攻击2.2.3 安全保护等级 2.3计算机病毒与木马2.4安全防范体系 1、安全基础技术…...

ActiveMQ 07 集群配置

Active MQ 07 集群配置 官方文档 http://activemq.apache.org/clustering 主备集群 http://activemq.apache.org/masterslave.html Master Slave TypeRequirementsProsConsShared File System Master SlaveA shared file system such as a SANRun as many slaves as requ…...

Redis(哨兵模式)

什么是哨兵机制 问题: redis 主从复制模式下, 一旦主节点由于故障不能提供服务, 需要人工进行主从切换, 同时大量客户端需要被通知切换到新的主节点上, 对于有一定规模的应用来说, 对于人力的资源消耗会很大.解决: 通过哨兵对主从结构进行监控, 一旦出现主节点挂了的情况, 自动…...

一种基于镜像指示位办法的RingBuffer实现,解决Mirror和2的幂个数限制

简介 在嵌入式开发中&#xff0c;经常有需要用到RingBuffer的概念&#xff0c;在RingBuffer中经常遇到一个Buffer满和Buffer空的判断的问题&#xff0c;一般的做法是留一个单位的buffer不用&#xff0c;这样做最省事&#xff0c;但是当RingBuffer单位是一个结构体时&#xff0…...

【Java开发指南 | 第十一篇】Java运算符

读者可订阅专栏&#xff1a;Java开发指南 |【CSDN秋说】 文章目录 算术运算符关系运算符位运算符逻辑运算符赋值运算符条件运算符&#xff08;?:&#xff09;instanceof 运算符Java运算符优先级 Java运算符包括&#xff1a;算术运算符、关系运算符、位运算符、逻辑运算符、赋值…...

【IC前端虚拟项目】验证环境方案思路和文档组织

【IC前端虚拟项目】数据搬运指令处理模块前端实现虚拟项目说明-CSDN博客 对于mvu的验证环境,从功能角度就可以分析出需要搭建哪些部分,再看一下mvu的周围环境哈: 很明显验证环境必然要包括几个部分: 1.模拟idu发送指令; 2.模拟ram/ddr读写数据; 3.rm模拟mvu的行为; …...

程序设计|C语言教学——C语言基础1:C语言的引入和入门

一、程序的执行 1.定义 解释&#xff1a;借助一个程序&#xff0c;那个程序能够试图理解你的程序&#xff0c;然后按照你的要求执行。下次执行的时候还需要从零开始解释。 编译&#xff1a;借助一个程序&#xff0c;能够像翻译官一样&#xff0c;把你的程序翻译成机器语言&a…...

初学python记录:力扣928. 尽量减少恶意软件的传播 II

题目&#xff1a; 给定一个由 n 个节点组成的网络&#xff0c;用 n x n 个邻接矩阵 graph 表示。在节点网络中&#xff0c;只有当 graph[i][j] 1 时&#xff0c;节点 i 能够直接连接到另一个节点 j。 一些节点 initial 最初被恶意软件感染。只要两个节点直接连接&#xff0c…...

LlamaIndex 组件 - Storing

文章目录 一、储存概览1、概念2、使用模式3、模块 二、Vector Stores1、简单向量存储2、矢量存储选项和功能支持3、Example Notebooks 三、文件存储1、简单文档存储2、MongoDB 文档存储3、Redis 文档存储4、Firestore 文档存储 四、索引存储1、简单索引存储2、MongoDB 索引存储…...

在Linux系统中设定延迟任务

一、在系统中设定延迟任务要求如下&#xff1a; 要求&#xff1a; 在系统中建立easylee用户&#xff0c;设定其密码为easylee 延迟任务由root用户建立 要求在5小时后备份系统中的用户信息文件到/backup中 确保延迟任务是使用非交互模式建立 确保系统中只有root用户和easylee用户…...

JVM之方法区的详细解析

方法区 方法区&#xff1a;是各个线程共享的内存区域&#xff0c;用于存储已被虚拟机加载的类信息、常量、即时编译器编译后的代码等数据&#xff0c;虽然 Java 虚拟机规范把方法区描述为堆的一个逻辑部分&#xff0c;但是也叫 Non-Heap&#xff08;非堆&#xff09; 设置方法…...

Go 使用ObjectID

ObjectID介绍 MongoDB中的ObjectId是一种特殊的12字节 BSON 类型数据&#xff0c;用于为主文档提供唯一的标识符&#xff0c;默认情况下作为 _id 字段的默认值出现在每一个MongoDB集合中的文档中。以下是ObjectId的具体组成&#xff1a; 1. 时间戳&#xff08;Timestamp&…...

基于SpringBoot+Vue的疾病防控系统设计与实现(源码+文档+包运行)

一.系统概述 在如今社会上&#xff0c;关于信息上面的处理&#xff0c;没有任何一个企业或者个人会忽视&#xff0c;如何让信息急速传递&#xff0c;并且归档储存查询&#xff0c;采用之前的纸张记录模式已经不符合当前使用要求了。所以&#xff0c;对疾病防控信息管理的提升&a…...

2024年阿里云4核8G配置云服务器价格低性能高!

阿里云4核8G服务器租用优惠价格700元1年&#xff0c;配置为ECS通用算力型u1实例&#xff08;ecs.u1-c1m2.xlarge&#xff09;4核8G配置、1M到3M带宽可选、ESSD Entry系统盘20G到40G可选&#xff0c;CPU采用Intel(R) Xeon(R) Platinum处理器&#xff0c;阿里云优惠 aliyunfuwuqi…...

关于ContentProvider这一遍就够了

ContentProvider是什么&#xff1f; ContentProvider是Android四大组件之一&#xff0c;主要用于不同应用程序之间或者同一个应用程序的不同部分之间共享数据。它是Android系统中用于存储和检索数据的抽象层&#xff0c;允许不同的应用程序通过统一的接口访问数据&#xff0c;…...

《1w实盘and大盘基金预测 day23》

这几天预测错麻了&#xff0c;哈哈哈&#xff0c;完全和技术没关系&#xff0c;全是消息面。 昨日预测&#xff1a; 2958-2984-3010 证券继续下跌&#xff0c;昨天诱多把我诱惑进去了&#xff08;看2-3天的反弹也没了&#xff09;&#xff0c;今天直接出掉昨天买的。 整体操作…...

向量数据库与图数据库:理解它们的区别

作者&#xff1a;Elastic Platform Team 大数据管理不仅仅是尽可能存储更多的数据。它关乎能够识别有意义的见解、发现隐藏的模式&#xff0c;并做出明智的决策。这种对高级分析的追求一直是数据建模和存储解决方案创新的驱动力&#xff0c;远远超出了传统关系数据库。 这些创…...

WIN7用上最新版Chrome

1.下载WIN10最新版Chrome的离线安装包 谷歌浏览器 Chrome 最新版离线安装包下载地址 v123.0.6312.123 - 每日自动更新 | 异次元软件 文件名称&#xff1a;123.0.6312.123_chrome_installer.exe。 123.0.6312.123_chrome_installer.exe 文件右键解压缩得到 chrome.7z&#x…...

node.jd版本降级/升级

第一步.先清空本地安装的node.js版本 按健winR弹出窗口&#xff0c;键盘输入cmd,然后敲回车&#xff08;或者鼠标直接点击电脑桌面最左下角的win窗口图标弹出&#xff0c;输入cmd再点击回车键&#xff09; 进入命令控制行窗口&#xff0c;输入where node&#xff0c;查看本地…...

python+playwright 学习-88 禁止加载图片等资源

前言 对于爬虫的小伙伴来说,有时候只需抓取页面的文本,不用加载图片,可以加快操作页面速度,那么我们可以设置禁止加载图片等资源。 禁止图片加载 根据url地址的后缀,图片资源后缀一般是png,jpg,jpeg,gif等格式。 from playwright.sync_api import sync_playwrightwith…...

Linux:Redis7.2.4的简单在线部署(1)

注意&#xff1a;我写的这个文章是以最快速的办法去搭建一个redis的基础环境&#xff0c;作用是为了做实验简单的练习&#xff0c;如果你想搭建一个相对稳定的redis去使用&#xff0c;可以看我下面这个文章 Linux&#xff1a;Redis7.2.4的源码包部署&#xff08;2&#xff09;-…...

HackMyVM-Connection

目录 信息收集 arp nmap WEB web信息收集 dirsearch smbclient put shell 提权 系统信息收集 suid gdb提权 信息收集 arp ┌─[rootparrot]─[~/HackMyVM] └──╼ #arp-scan -l Interface: enp0s3, type: EN10MB, MAC: 08:00:27:16:3d:f8, IPv4: 192.168.9.115 S…...

Prometheus接入AlterManager配置邮件告警(基于K8S环境部署)

目录 一.配置Alertmanager告警发送至邮箱二.Prometheus接入AlertManager三.部署PrometheusAlterManager(放到一个Pod中)四. 测试告警 基于 此环境做实验 一.配置Alertmanager告警发送至邮箱 1.创建AlertManager ConfigMap资源清单 vim alertmanager-cm.yaml --- kind: Confi…...

find方法

find() 方法用于在数组中查找符合条件的第一个元素&#xff0c;并返回该元素。如果找到匹配的元素&#xff0c;则返回该元素的值&#xff1b;如果未找到匹配的元素&#xff0c;则返回 undefined。 例如: const firstWithdrawal movements.find(mov > mov < 0); consol…...

TLS v1.3 导致JetBrains IDE jdk.internal.net.http.common CPU占用高

开发环境 GoLand版本&#xff1a;2022.3.4 问题原因 JDK 中的 TLS v1.3 实现引起 解决办法 使用 SOCKS 代理代替HTTP代理 禁用 Space 和 Code With Me 插件 禁用 TLS v1.3&#xff0c;参考&#xff1a;https://stackoverflow.com/questions/54485755/java-11-httpclient-…...

计算机网络 2.2数据传输方式

第二节 数据传输方式 一、数据通信系统模型 添加图片注释&#xff0c;不超过 140 字&#xff08;可选&#xff09; 1.数据终端设备&#xff08;DTE&#xff09; 作用&#xff1a;用于处理用户数据的设备&#xff0c;是数据通信系统的信源和信宿。 设备&#xff1a;便携计算机…...

陇剑杯 流量分析 webshell CTF writeup

陇剑杯 流量分析 链接&#xff1a;https://pan.baidu.com/s/1KSSXOVNPC5hu_Mf60uKM2A?pwdhaek 提取码&#xff1a;haek目录结构 LearnCTF ├───LogAnalize │ ├───linux简单日志分析 │ │ linux-log_2.zip │ │ │ ├───misc日志分析 │ │ …...

好看的网站排版/腾讯朋友圈广告投放价格

&#xff08;本文转载自www.spdiy.com视频DIY家园&#xff09; 在此&#xff0c;我对这些募捐情况进行了一下大概的统计。。初步统计的可以看得见&#xff0c;有名有数的ZF&#xff0c;企业及个人的募捐款为&#xff1a;196492万元。另外再加上没有统计在内的各种救灾物质&am…...

龙游网站建设的公司/提高关键词排名的软文案例

在HTML5中&#xff0c;1. 新增了通过JS在浏览器历史记录中添加项目的功能。2. 在不刷新页面的前提下显示改变浏览器地址栏中的URL。3. 添加了当用户单击浏览器的后退按钮时触发的事件。通过以上三点&#xff0c;可以实现在不刷新页面的前提下动态改变浏览器地址栏中的URL&#…...

wordpress地区分站/设计网站模板

为 key 中所储存的值加上浮点数增量 increment 。如果 key 不存在&#xff0c;那么 INCRBYFLOAT 会先将 key 的值设为 0 &#xff0c;再执行加法操作。如果命令执行成功&#xff0c;那么 key 的值会被更新为&#xff08;执行加法之后的&#xff09;新值&#xff0c;并且新值会以…...

外省公司做网站备案/免费的云服务器有哪些

1 案例1&#xff1a;加密与解密应用 1.1 问题 本案例要求采用gpg工具实现加/解密及软件签名等功能&#xff0c;分别完成以下任务&#xff1a; 检查文件的MD5校验和 使用GPG实现文件机密性保护&#xff0c;加密和解密操作 使用GPG的签名机制&#xff0c;验证数据的来源正确性123…...

东莞常平镇房价多少/广州专做优化的科技公司

题目 句子仅由小写字母&#xff08;‘a’ 到 ‘z’&#xff09;、数字&#xff08;‘0’ 到 ‘9’&#xff09;、连字符&#xff08;’-’&#xff09;、标点符号&#xff08;’!’、’.’ 和 ‘,’&#xff09;以及空格&#xff08;’ &#xff09;组成。每个句子可以根据空格…...

响应式网站概况/深圳网络推广外包

LSM Tree(Log Structured Merge Trees)数据组织方式被应用于多种数据库&#xff0c;如LevelDB、HBase、Cassandra等&#xff0c;下面我们从为什么使用LSM tree、LSM tree的实现思路两方面介绍这种存储组织结构&#xff0c;完成对LSM tree的初步了解。 存储背景回顾 LSM tree相…...