YDB基本使用详解(转)
第七章YDB基本使用详解
一、如何与YDB对接(交互)
二、命令行接入
2.通过./sql.sh -f xxx.sql 直接执行文件中的SQL
三、WEB接入
WEB接口主要是为了给那些不支持HDBC访问的程序提供接口支持,如PHP。
http://xxx.xx.xx.xx:1210/sparkview
http://xxx.xx.xx.xx:1210/sparksql?sql=?
四、JDBC接口
1.JDBC接入方式连接字符串
Connection conn = DriverManager.getConnection("jdbc:hive2://ydbmaster:10009/default", "hdfs", "");
l10009表示JDBC的端口号,配置的值在ya100_evn.sh里面可以找到
lhdfs表示连接时所使用的Hadoop账号,大家也要跟配置文件中一致,以免其他未知账号产生垃圾文件没有及时的清理掉,以及造成Hadoop权限问题。
这个账号的配置目前存在两个位置,请大家配置一致,使用同一个账号。
2.JAVA编程接口
Class.forName("org.apache.Hive.jdbc.HiveDriver");
Connection conn = DriverManager.getConnection("jdbc:hive2://ydbmaster:10009/default", "hdfs", "");
Statement smst = conn.createStatement();
ResultSetMetaData m = rs.getMetaData();
int columns = m.getColumnCount();
for (int i = 1; i <= columns; i++) {
System.out.print(m.getColumnName(i));
for (int i = 1; i <= columns; i++) {
System.out.print(rs.getString(i));
依赖的JDBC客户端jar包可以从这个地址获取,本质上就是HIVE的thrift接口,依赖的jar包也是Hive的jar包
3.通过可视化SQL分析统计接入
SQL分析工具有很多,只要支持HIVE接口即可,免费的有Squirrel、收费的有DbVisualizer等
4.通过报表分析工具接入
通过可视化报表分析工具,可以极大的提高程序开发的效率,只要是支持HIVE接口的可视化报表工具,都可以与YDB集成,下面以帆软报表为例。
五、YDB分区
1.关于分区的说明
一条数据的分区,在导入的时候直接指定,具体请参考后面的数据导入用法。
如果按照日期进行分区,每天就会生成一个分区,如需查询哪天的数据,就去对应的分区中检索,其他的分区则闲置。
YDB 的SQL需要通过ydbpartion来指定分区; SQL查询必须要设置分区,而且要写在SQL的最外层。
ydbpartion in ('20140928','20140927')
目前不支持大于等于,小于等于的范围指定分区,仅支持等于与in的方式。
2.关于分区的数量与粒度,控制多少比较好?
l如果我们的数据可以按照时间进行切分,是不是切分的越细越好?
很遗憾,YDB并不适合特别多的分区,分区越多代表索引文件越多
2)YDB在一个进程里能够打开的索引数量是有限的,如果超过了打开的索引文件数量,那么就要关闭一些索引,以保证内存不会OOM。
基本原则就是在避免索引频繁的打开与关闭的情况下,索引粒度越小越好。
1)如果我们的数量不是很大,一年加在一起还不到10亿,那么我就建议采用按年分区。
2)如果我们的数据处于中等,每月的数据增量为1亿左右,那么我们建议按照季度分区。
3)如果我们的数据每天写入量特别大,如果按照月份分区,单个索引太大会造成写入瓶颈,那么我们建议按照天进行分区。
1)最近一两天的数据经常被查询,我们最近3天的数据按照天进行分区
2)但是偶尔也会发生查询整年的数据,如果采用按天分区的话,一次打开的索引太多,那么我们可以再加一个按照季度的分区。
3)按天的数据分区只保存最近7天的数据,超过7天的数据会通过insert的方式归档按照季度的分区里。
六、YDB的数据类型
1.基本类型
YDB类型 |
只索引 |
只存储 |
Hive类型 |
解释 |
string |
synn |
--- |
string |
字符串类型,该类型不分词,通常用来存储比较短的字符串,如类目 |
tint |
tiynn |
--- |
int |
整形32位-适合大范围的range过滤查询 |
tlong |
tlynn |
--- |
bigint |
整形64位-适合大范围的range过滤查询 |
tdouble |
tdynn |
--- |
double |
Double类型-适合大范围的range过滤查询 |
tfloat |
tfynn |
--- |
float |
Float类型-适合大范围的range过滤查询 |
int |
iynn |
--- |
int |
整形32位,占用存储空间少,但是范围查找性能低 |
long |
lynn |
--- |
bigint |
整形64位,占用存储空间少,但是范围查找性能低 |
double |
dynn |
--- |
double |
Double类型,占用存储空间少,但是范围查找性能低 |
float |
fynn |
--- |
float |
Float类型,占用存储空间少,但是范围查找性能低 |
geopoint |
--- |
--- |
bigint |
用于地理位置搜索-使用方法详见《26.地理位置感知搜索.txt》 |
2.分词类型
分词( Word Segmentation) 指的是将一个词字序列切分成一个一个单独的词。分词就是将连续的词序列按照一定的规范重新组合成词序列的过程.
分词类型,均为按行存储,在YDB中可以进行模糊检索,但是不能在SQL里面进行group by(YSQL函数以外是可以的)。
YDB类型 |
只索引 |
只存储 |
Hive类型 |
解释 |
simpletext |
simpletextyn |
simpletextny |
string |
ydb内置的普通文本分词 采用1~3元分词 |
haoma |
haomayn |
haomany |
string |
ydb内置的适合号码类型的分词,采用3~5元分词实现,分词粒度为char |
chepai |
chepaiyn |
chepainy |
string |
ydb内置的适合号码类型的分词,采用2~5元分词实现,分词粒度为char |
text |
tyn |
tny |
string |
为lucene默认的standard分词,在(处理手机号,邮箱,IP地址,网址等中英文与字典组合的数据上 不准确,请慎用) |
cjkyy |
cjkyn |
cjkny |
string |
为lucene默认的cjk分词即二元分词 (处理手机号,邮箱,IP地址,网址等中英文与字典组合的数据上 不准确,请慎用) |
以下类型除了分词外,还保存了分词后的词的顺序 ,可以进行顺序匹配
YDB类型 |
只索引 |
只存储 |
Hive类型 |
解释 |
charlike |
--- |
--- |
string |
按照字符char 1~5元分词 (效果较好,term区分了词元,适合车牌,手机号类型的较短文本) |
wordlike |
--- |
--- |
string |
按字与词 1~3元分词 (效果较好,term区分了词元,适合文本类型) |
pchepai |
--- |
--- |
string |
按照字符char 2~5元分词 |
phaoma |
--- |
--- |
string |
按照字符char 3~5元分词 |
psimpletext |
--- |
--- |
string |
按字与词 1~3元分词 |
pyy |
pyn |
pny |
string |
lucene的cjk分词,中文采用二元分词,英文与数字采用 单字分词 |
3.多值列类型
有些时候,我们想在一个列里面存储多个值的时候,就可以考虑使用多值列了
比如说,可以将一个人 的多个标签值 存储在一个记录里面,一个人的每天的行为数据 放在一个记录里面。
1.字符串类型的多值列,返回的值的无序,并且是排重的,故这块有额外注意。
2.数值型的则是有序的(与导入的顺序一致),并且是没有排重的。
YDB类型 |
Hive类型 |
解释 |
mt_syn |
string |
string类型的多值列 |
mt_tlyn |
string |
tlong类型的多值列 |
mt_lyn |
string |
long类型的多值列 |
mt_tdyn |
string |
tdouble类型的多值列 |
mt_dyn |
string |
double类型的多值列 |
mt_iyn |
string |
int类型的多值列 |
mt_tiyn |
string |
tint类型的多值列 |
mt_fyn |
string |
float类型的多值列 |
mt_tfyn |
string |
tfolat类型的多值列 |
七、创建YDB表
八、将HIVE表中的数据导入到YDB中
通过ydbpartion表向YDB中导入数据,下面示例中的ydb_example_shu为YDB表的表名,3000w为YDB表的分区名。
1.直接追加数据
select 'ydb_example_shu', '3000w', '',
2.覆盖数据
insert overwrite table ydbpartion
select 'ydb_example_shu', '3000w', '',
3.在追加数据前,先执行按条件删除
select 'ydb_example_shu', '3000w', 'ydb_sex='男' and ydb_blood='A'',
4.HIVE表数据导入优化-控制并发数
1)启动时候的Map数量不容易控制,如果启动的map数量很多,而Spark又没有容量调度器,会占满所有的资源,影响查询。
2)所以很多时候我们的业务期望,在进行数据导入的时候,不要启动太多的Map数量,而是希望留出一部分资源,能让给查询,于是控制Map数量就显得特别重要了。
3)我们导入数据,倾向于数据能更均衡一些,这样查询的时候,不会因为数据倾斜而影响性能。
CREATE external table ydb_import_txt(
row format delimited fields terminated by ','
INPUTFORMAT 'cn.net.ycloud.ydb.handle.YdbCombineInputFormat'
OUTPUTFORMAT 'org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat'
'ydb.combine.input.format.raw.format'='org.apache.hadoop.mapred.TextInputFormat'
select count(*) from ydb_import_txt limit 10;
insert overwrite table ydbpartion
select 'ydb_example_shu', 'txt', '',
select count(*) from ydb_example_shu where ydbpartion = 'txt'
CREATE external table ydb_import_rcfile(
ROW FORMAT SERDE 'org.apache.hadoop.hive.serde2.columnar.LazyBinaryColumnarSerDe'
INPUTFORMAT 'cn.net.ycloud.ydb.handle.YdbCombineInputFormat'
OUTPUTFORMAT 'org.apache.hadoop.hive.ql.io.RCFileOutputFormat'
'ydb.combine.input.format.raw.format'='org.apache.hadoop.hive.ql.io.RCFileInputFormat'
insert overwrite table ydb_import_rcfile select * from ydb_import_txt;
select count(*) from ydb_import_rcfile limit 10;
insert overwrite table ydbpartion
select 'ydb_example_shu', 'rcfile', '',
select count(*) from ydb_example_shu where ydbpartion = 'rcfile'
drop table ydb_import_sequencefile;
CREATE external table ydb_import_sequencefile(
ROW FORMAT SERDE 'org.apache.hadoop.hive.serde2.columnar.LazyBinaryColumnarSerDe'
INPUTFORMAT 'cn.net.ycloud.ydb.handle.YdbCombineInputFormat'
OUTPUTFORMAT 'org.apache.hadoop.hive.ql.io.HiveSequenceFileOutputFormat'
'ydb.combine.input.format.raw.format'='org.apache.hadoop.mapred.SequenceFileInputFormat'
SET hive.exec.compress.output=true;
SET mapred.output.compression.codec=org.apache.hadoop.io.compress.DefaultCodec;
SET mapred.output.compression.type=BLOCK;
insert overwrite table ydb_import_sequencefile select * from ydb_import_txt;
select count(*) from ydb_import_sequencefile limit 10;
insert overwrite table ydbpartion
select 'ydb_example_shu', 'sequencefile', '',
select count(*) from ydb_example_shu where ydbpartion = 'sequencefile'
###Spark内部对SERDE含有Parquet格式的类名进行了特殊处理,会导致设置的inputformat不生效,所以YDB也特殊处理下,就换成不含有Parquet的名字
drop table ydb_import_parquet;
CREATE external table ydb_import_parquet(
ROW FORMAT SERDE 'cn.net.ycloud.ydb.handle.combine.YdbParHiveSerDe'
INPUTFORMAT 'cn.net.ycloud.ydb.handle.YdbCombineInputFormat'
OUTPUTFORMAT 'cn.net.ycloud.ydb.handle.combine.YdbParMapredParquetOutputFormat'
set parquet.block.size=16777216;
insert overwrite table ydb_import_parquet select * from ydb_import_txt;
select count(*) from ydb_import_parquet limit 10;
insert overwrite table ydbpartion
select 'ydb_example_shu', 'parquet', '',
select count(*) from ydb_example_shu where ydbpartion = 'parquet'
九、YDB 查询SQL 写法
/*ydb.pushdown('->')*/ 与 /*('<-')pushdown.ydb*/ 前后包含起来,以方便解析
1.基本示例
select count(*) from ydb_example_shu where ydbpartion = '2015'
select * from ydb_example_shu where ydbpartion = '3000w' limit 10
select content,usernick from ydb_example_shu where ydbpartion = '3000w' and content='王老吉' limit 10
select sum(amtdouble) from ydb_example_shu where ydbpartion = '3000w'
select avg(amtdouble) as avgamt from ydb_example_shu where ydbpartion = '3000w'
select count(*),count(amtdouble),avg(amtdouble),sum(amtdouble),min(amtdouble),max(amtdouble)
,min(ydb_province),max(ydb_province) from ydb_example_shu where ydbpartion = '3000w'
select ydb_sex, phonenum,amtlong,amtdouble
from ydb_example_shu where ydbpartion='3000w' order by amtdouble desc ,amtlong limit 10
2.YDB特有的BlockSort排序(排序大跃进)
由于BlockSort是借助搜索的索引来实现的,所以采用blockSort的排序,不需要暴力扫描,性能有大幅度的提升。
BlockSort的排序,并非是预计算的方式,可以全表进行排序,也可以基于任意的过滤筛选条件进行过滤排序。
正常写法 |
blockSort写法 |
|
单列升序 |
/*ydb.pushdown('->')*/ select tradetime, nickname from blocksort_ydb order by tradetime limit 10 /*('<-')pushdown.ydb*/; |
/*ydb.pushdown('->')*/ select tradetime, nickname from blocksort_ydb where ydbkv='blocksort.field:tradetime' and ydbkv='blocksort.limit:10' order by tradetime limit 10 /*('<-')pushdown.ydb*/; |
单列降序 |
/*ydb.pushdown('->')*/ select tradetime, nickname from blocksort_ydb order by tradetime desc limit 10 /*('<-')pushdown.ydb*/; |
/*ydb.pushdown('->')*/ select tradetime, nickname from blocksort_ydb where ydbkv='blocksort.field:tradetime' and ydbkv='blocksort.limit:10' and ydbkv='blocksort.desc:true' order by tradetime desc limit 10 /*('<-')pushdown.ydb*/; |
3.数据导出
----导出数据到hive表
insert overwrite table ydb_import_importtest
/*ydb.pushdown('->')*/
select phonenum,usernick,ydb_sex,ydb_province,
ydb_grade,ydb_age,ydb_blood,ydb_zhiye,ydb_earn,
ydb_prefer,ydb_consume,ydb_day,amtdouble,amtlong,content
from ydb_example_shu where ydbpartion = '3000w'
/*('<-')pushdown.ydb*/;
#有limit的导出示例 (在Spark的当前版本有BUG,需要采用如下变通方法解决)
insert overwrite table ydb_import_importtest
select * from (
/*ydb.pushdown('->')*/
select
phonenum,usernick,ydb_sex,ydb_province,ydb_grade,ydb_age,ydb_blood,ydb_zhiye,ydb_earn,ydb_prefer,ydb_consume,ydb_day,amtdouble,amtlong,content
from ydb_example_shu where ydbpartion = '3000w' and ydbkv='export.max.return.docset.size:1000'
/*('<-')pushdown.ydb*/
) tmp order by rand() limit 1000;
----数据导出到YDB的其他分区里示例
insert overwrite table ydbpartion
select 'ydb_example_shu', 'test3', '',
YROW(
'phonenum',tmp.phonenum,
'usernick',tmp.usernick,
'ydb_sex',tmp.ydb_sex,
'ydb_province',tmp.ydb_province,
'ydb_grade',tmp.ydb_grade,
'ydb_age',tmp.ydb_age,
'ydb_blood',tmp.ydb_blood,
'ydb_zhiye',tmp.ydb_zhiye,
'ydb_earn',tmp.ydb_earn,
'ydb_prefer',tmp.ydb_prefer,
'ydb_consume',tmp.ydb_consume,
'ydb_day',tmp.ydb_day,
'amtdouble',tmp.amtdouble,
'amtlong',tmp.amtlong,
'content',tmp.content
)
from (
/*ydb.pushdown('->')*/
select
phonenum,usernick,ydb_sex,ydb_province,ydb_grade,ydb_age,ydb_blood,ydb_zhiye,ydb_earn,ydb_prefer,ydb_consume,ydb_day,amtdouble,amtlong,content
from ydb_example_shu where ydbpartion = '3000w'
/*('<-')pushdown.ydb*/
) tmp
;
----导出数据到HDFS
由于Spark当前版本无法通过insert Directory的方式直接导出数据到HDFS,但是可以将数据导出到Hive表,故数据导出到HDFS可以通过导出到Hive表变通的方式来解决
可以通过创建一个导出表来解决
CREATE external table ydb_import_importtest(
phonenum bigint, usernick string, ydb_sex string, ydb_province string, ydb_grade string, ydb_age string, ydb_blood string, ydb_zhiye string, ydb_earn string, ydb_prefer string, ydb_consume string, ydb_day string, amtdouble double,amtlong int,content string
)location '/data/example/ydb_import_importtest';
如果我们创建表的时候,没有加location,我们可以通过show create table xxx表名 可以看到location的位置
4.多表关联示例
select k1.vehiclePlate as vehiclePlate from (
select vehiclePlate,tollCode from vehiclepass where ydbpartion = '3000w' and tollCode='1'
select vehiclePlate,tollCode from vehiclepass where ydbpartion = '3000w' and tollCode='2'
on (k1.vehiclePlate=k2.vehiclePlate);
select k1.vehiclePlate as vehiclePlate,k2.vehiclePlate from (
select vehiclePlate,tollCode from vehiclepass where ydbpartion = '3000w' and tollCode='1'
select vehiclePlate,tollCode from vehiclepass where ydbpartion = '3000w' and tollCode='1'
on (k1.vehiclePlate=k2.vehiclePlate);
+---------------+---------------+--+
| vehiclePlate | vehiclePlate |
+---------------+---------------+--+
+---------------+---------------+--+
select k1.vehiclePlate as vehiclePlate from (
select vehiclePlate,tollCode from vehiclepass where ydbpartion = '3000w' and tollCode='1'
select vehiclePlate,tollCode from vehiclepass where ydbpartion = '3000w' and tollCode='2'
on (k1.vehiclePlate=k2.vehiclePlate)
select vehiclePlate,tollCode from vehiclepass where ydbpartion = '3000w' and tollCode='3'
) k22 on k21.vehiclePlate=k22.vehiclePlate order by k21.vehiclePlate;
select k21.vehiclePlate,k22.vehiclePlate from(
select k1.vehiclePlate as vehiclePlate from (
select vehiclePlate,tollCode from vehiclepass where ydbpartion = '3000w' and tollCode='1'
select vehiclePlate,tollCode from vehiclepass where ydbpartion = '3000w' and tollCode='2'
on (k1.vehiclePlate=k2.vehiclePlate)
select vehiclePlate,tollCode from vehiclepass where ydbpartion = '3000w' and tollCode='3'
) k22 on k21.vehiclePlate=k22.vehiclePlate ;
+---------------+---------------+--+
| vehiclePlate | vehiclePlate |
+---------------+---------------+--+
+---------------+---------------+--+
5)----三个卡口 先left SEMI join 之后再 left join
select k21.vehiclePlate,k22.vehiclePlate from(
select k1.vehiclePlate as vehiclePlate from (
select vehiclePlate,tollCode from vehiclepass where ydbpartion = '3000w' and tollCode='1'
select vehiclePlate,tollCode from vehiclepass where ydbpartion = '3000w' and tollCode='2'
on (k1.vehiclePlate=k2.vehiclePlate)
select vehiclePlate,tollCode from vehiclepass where ydbpartion = '3000w' and tollCode='3'
) k22 on k21.vehiclePlate=k22.vehiclePlate ;
+---------------+---------------+--+
| vehiclePlate | vehiclePlate |
+---------------+---------------+--+
+---------------+---------------+--+
5.UNION示例
select count(*) as cnt from ydb_example_shu where ydbpartion = '3000w'
select count(*) as cnt from ydb_example_shu where ydbpartion = '300winsert'
select count(*) as cnt from ydb_example_shu where ydbpartion = '300winsert2'
select count(*) as cnt from ydb_example_shu where ydbpartion = '3000w' and content='王老吉'
select count(*) as cnt from ydb_example_shu where ydbpartion = '20151011' and content='工商银行'
select count(*) as cnt from ydb_example_shu where ydbpartion = '20151011'
2)--union order by的结果,注意,这里有个子查询SQL
6.DISTINCT示例
-----#####如果distinct的数据并不多,可以考虑采用collect_set 性能较好#######
1)----####直接count distinct##########
size(collect_set(tmp.ydb_sex)) as dist_sex,
size(collect_set(tmp.ydb_province)) as dist_province,
count(tmp.amtlong) as cnt_long,
count(distinct tmp.amtlong) as dist_long
2)----group by 加 count distinct####
size(collect_set(tmp.ydb_province)) as dist_province,
count(tmp.amtlong) as cnt_long,
count(distinct tmp.amtlong) as dist_long
group by tmp.ydb_sex limit 10;
7.行转列示例
)tmp group by ydb_sex limit 10;
)tmp group by ydb_province order by scnt desc limit 10;
)tmp group by ydb_province order by scnt desc limit 10;
)tmp group by ydb_day order by scnt desc limit 10;
8.对于时间的高效处理
存储的值 转换成 yyyyMMddhhmmss ,这样是定长的,而且可读性好(比unix时间磋可读性好)
如果时间精度是 秒 ,毫秒,纳秒的 话 一定要使用 tlong (范围查找比long快很多),如果是天,小时的话,可以使用long 节省存储空间
select (2017-cast(substring('201831198307123487',7,4) as bigint) ) from spark_txt limit 10;
9.null值与空值的匹配
##############null值的匹配非常消耗性能,采用暴力扫描倒排表的方式实现,如果该列的值排重后的值特别多,如sessionId,身份证号码,手机号等,请慎用########
####如果是检索明细数据,建议在hive层进行过滤####
####TODO 未来可以通过标签里面的live bits改进null值匹配的性能####
10.近似文本匹配
有些时候,我们只想找到一篇跟当前指定文章类似的文章。可能中间相差几个字不一样无所谓,或者局部的字顺序前后颠倒也无所谓。
b)并不考虑单词顺序(虽然伪造的数据是有顺序的,但是匹配是不考虑顺序的)。
d)匹配是按照分词的结果后进行匹配的,并不是按照空格进行拆分的,具体如何检验分词,
==通过wt与score参数将content模糊匹配的权重增大
11.多值列示例
有些时候,我们想在一个列里面存储多个值的时候,就可以考虑使用多值列了
比如说,可以将一个人 的多个标签值 存储在一个记录里面,一个人的每天的行为数据 放在一个记录里面。
1.字符串类型的多值列,返回的值的无序,并且是排重的,故这块有额外注意。
2.数值型的则是有序的(与导入的顺序一致),并且是没有排重的。
3.传递的数值是按照空格 拆分的 ,如 11 22 33 44
5.只要数据类型定义为多之列,程序目前会按照空格识别来将传入的数据拆分成多个值分别存储
4)--两个多值列group by ,(笛卡尔集,要注意内存,以及性能,要慎重)
12.地理位置感知搜索
1)测试表的创建,注意使用mortonhash的列的类型是geopoint
create table lonlattable_test(
2)导入数据-注意YMortonHash函数是用于生成Morton数的,将来在索引中用于匹配
insert overwrite table ydbpartion
select 'lonlattable_test', '3000w', '',
'mortonhash',YMortonHash(r[0],r[1])
3)#数据预览,注意YMortonUnHash用于将数据在还原为经纬度,YMortonHashDistance则用来计算距离,单位是m
select lon,lat,mortonhash from lonlattable_test where ydbpartion='3000w'
)tmp order by distance limit 10 ;
4)地理位置检索,给一个坐标,搜寻最近多少米远的所有记录,注意YGeo@的使用
)tmp order by distance limit 10 ;
5)####################按照矩形区域搜索isbox=true
)tmp order by distance limit 10 ;
13.考虑单词顺序的模糊匹配
默认YDB提供了simpletex,haoma等类型进行模糊匹配。
他们本质上是通过分词进行匹配,并不考虑匹配的词的顺序,如果要进行模糊匹配并且又要保证匹配的先后顺序,那么就需要在进行中文分词的时候保存词的位置。
如果保存了顺序,我们可以通过Ylike@方法 按照单词顺序进行匹配查询
phonenum='Ylike@188*2*6*3*6*88'
content='Ylike@14 15 * 24 28 * 37 41 '
charlike: 按照字符char 1~5元分词 (效果较好,term区分了词元,适合车牌,手机号类型的较短文本)
wordlike: 按字与词 1~3元分词 (效果较好,term区分了词元,适合文本类型)
pyy :lucene的cjk分词,中文采用二元分词,英文与数字采用 单字分词
注意:目前的这种Ylike还实现不了前缀与后缀匹配,如果要进行前缀与后缀匹配,建议在导入数据前,加入前缀与后缀的特殊符号
这样进行前缀匹配的时候,可以通过phonenum='Ylike@start192.168' 来匹配,后缀匹配可以通过 phonenum='Ylike@3.40end' 来进行匹配
select phonenum from ydb_example_shu_positon where ydbpartion = '3000w' and phonenum='Ylike@824963'
8 rows selected (0.272 seconds)
select phonenum from ydb_example_shu_positon where ydbpartion = '3000w' and phonenum='Ylike@824*963'
19 rows selected (0.26 seconds)
4 rows selected (0.241 seconds)
4.通过* 允许中间某些词 不连续,但依然保证顺序######
14.管理员命令
select count(*) from ydb_example_shu where ydbpartion='3000w' and ydbkv='ydb.truncate:true'
drop table ydb_example_shu partions 3000a4
drop table ydb_example_shu partions 3000a4,3000a5,3000a6
truncate table ydb_example_shu
--刷新缓冲区的数据,让其能被搜索到,(binlog会持久化但数据并不会立即持久化到hdfs)
--主动触发,将内存中的数据刷盘操作,(数据会被搜索到,并且持久化到磁盘)
select count(*) from ydb_example_trade where ydbpartion='k25_005_0' and ydbkv='ydb.force.sync:true'
15.变通方式的分页方案
默认Spark SQL无法进行分页,YDB由于使用了Spark也存在这个问题,故我们采取了变通方式来实现分页。
第一页 直接limit 10,并且将每一行的数据,都按pagekey取个crc32的值 存储在lru的hashmap中
第二页 直接limit 20,并且根据第一页的crc32与当前的20条记录进行移除,有可能剩余12条或更多,但至少剩余10条,然后取出10条返回,并且将crc32缓存在LRU的hashmap中
第三页 直接limit 30,同第二页一样,移除掉与crc32匹配的记录,返回10条并且添加第三页的crc32
这样一直处理到1024条记录 ,如果同时能处理1024个session,我们认为内存是能够放1024*1024个crc32的long类型
在这种方式下,由于需要与先前生成的crc32值进行排重,目前的实现没有精确控制返回的数据条数,而是返回介于pagesize到pagesize*2的记录数,
3.每页返回的行数是一个近似值,介于pagesize到pagesize*2的记录数。
4.sql中的 as pagekey与pagevalue 不能省略,本质是KV返回
如果数据表的规模很大,建议配置如下参数控制每个segments导出的记录条数,以免占用太多的HDFS空间
and ydbkv="export.max.return.docset.size:1000" and ydbkv="max.return.docset.size:1000"
CREATE external table ydb_page_session(
partitioned by (ydbsession string)
location '/data/ycloud/ydb/rawdata/ydb_page_session';
CREATE external table ydb_more_session(
partitioned by (ydbsession string)
location '/data/ycloud/ydb/rawdata/ydb_more_session';
注意生成的pagekey不能省略,用于排重,如果是查询明细可以用y_uuid_s的内置列填充。
16.分词
simpletext ydb内置的普通文本分词 采用1~3元分词
haoma ydb内置的适合号码类型的分词,采用3~5元分词实现,分词粒度为char
chepai ydb内置的适合号码类型的分词,采用2~5元分词实现,分词粒度为char
text 为lucene默认的standard分词,在(处理手机号,邮箱,IP地址,网址等中英文与字典组合的数据上 不准确,请慎用)
cjkyy 为lucene默认的cjk分词即二元分词 (处理手机号,邮箱,IP地址,网址等中英文与字典组合的数据上 不准确,请慎用)
ikyy与textik 为开源的ik分词的实现,采用词库分词,词库我们可以再lib下找到
以下类型除了分词外,还保存了分词后的词的顺序,可以进行顺序匹配 更多请参考《27.考虑单词顺序的模糊匹配》
charlike: 按照字符char 1~5元分词 (效果较好,term区分了词元,适合车牌,手机号类型的较短文本)
wordlike: 按字与词 1~3元分词 (效果较好,term区分了词元,适合文本类型)
pyy :lucene的cjk分词,中文采用二元分词,英文与数字采用 单字分词
YAnalyzer('charlike','query','中华人民123456') as charlikequery,
YAnalyzer('charlike','index','中华人民123456') as charlikeindex
select content from ydb_example_shu_multyvalue where ydbpartion='3000w'
YAnalyzer('wordlike','query','中华人民123456') as wordlikequery,
YAnalyzer('wordlike','index','中华人民123456') as wordlikeindex
select content from ydb_example_shu_multyvalue where ydbpartion='3000w'
| wordlikequery | wordlikeindex |
1 row selected (0.889 seconds)
YAnalyzer('phaoma','query','中华人民123456') as phaomaquery,
YAnalyzer('phaoma','index','中华人民123456') as phaomaindex
select content from ydb_example_shu_multyvalue where ydbpartion='3000w'
YAnalyzer('psimpletext','query','中华人民123456') as psimpletextquery,
YAnalyzer('psimpletext','index','中华人民123456') as psimpletextindex
select content from ydb_example_shu_multyvalue where ydbpartion='3000w'
+-------------------+---------------------------------------------------+--+
| psimpletextquery | psimpletextindex |
+-------------------+---------------------------------------------------+--+
| 中华人 华人民 人民123456 | 中 华 人 民 123456 中华 华人 人民 民123456 中华人 华人民 人民123456 |
+-------------------+---------------------------------------------------+--+
17.with as 写法简化SQL
如果我们的SQL,嵌套层级太深,可以考虑通过with as 方法,将子SQL抽取出来,让整体的SQL看起来逻辑更清晰,大家阅读SQL的时候也便于理解。
Hive 可以用with as将某个查询命名为一个临时的表名,其他语句可以随时使用该临时表名进行查询。
with q1 as (select * from src where key= ‘5’),
q2 as (select * from src s2 where key = ‘4’)
select * from q1 union all select * from q2;
select c_custkey from customer_ydb where c_mktsegment = 'BUILDING'
select l_orderkey,l_extendedprice,l_discount from lineitem_ydb where l_shipdate > '1995-03-15'
l_orderkey, sum(l_extendedprice*(1-l_discount)) as revenue, o_orderdate, o_shippriority
on l.l_orderkey = o.o_orderkey
group by l_orderkey, o_orderdate, o_shippriority
order by revenue desc, o_orderdate ,l_orderkey, o_shippriority
select n_name,n_regionkey,n_nationkey from nation_ydb
select r_regionkey,r_name from region_ydb where r_name = 'EUROPE'
select s_acctbal, s_name,s_address,s_phone, s_comment ,s_nationkey,s_suppkey
select ps_supplycost,ps_suppkey,ps_partkey
select p_partkey,p_mfgr,p_size,p_type
from part_ydb where p_size = 15 and p_type like '%BRASS'
q2_minimum_cost_supplier_tmp1 as (select
p.p_partkey = ps.ps_partkey ),
q2_minimum_cost_supplier_tmp2 as (
p_partkey, min(ps_supplycost) as ps_min_supplycost
t1.s_acctbal, t1.s_name, t1.n_name, t1.p_partkey, t1.p_mfgr, t1.s_address, t1.s_phone, t1.s_comment
q2_minimum_cost_supplier_tmp1 t1 join q2_minimum_cost_supplier_tmp2 t2
t1.p_partkey = t2.p_partkey and t1.ps_supplycost=t2.ps_min_supplycost
order by s_acctbal desc, n_name, s_name, p_partkey,p_mfgr,s_address,s_phone,s_comment
十、通过Kafka实时导入数据
默认的Kafka导入数据只支持Json格式,如果需要支持其他格式,需要自己通过Java写Parser.。
1.Kafka配置的注意点
第一:注意Kafka server 的num.partitions一定要大于YDB启动的进程*线程数量,否则有的进程消费不到数据
如果发现之前配置错了,要清空下ZK相关路径(现在好像有API接口了),否则修改完了也不生效
Kafka的启动很简单 ./kafka-server-start.sh ../config/server.properties
第二:请参考第四章的Kafka配置注意事项,这里不再重复介绍
2.YDB中配置Kafka的消费
在ydb_site.yaml中添加如下的配置,并更改相关连接参数
ydb.reader.list: "default,filesplit,kafka_json"
#如果您要使用其他的消息中间件,可以自定义Reader,默认为Kafka的实现
ydb.reader.read.class.kafka_json: "cn.net.ycloud.ydb.server.reader.kafka.KafkaDataReader"
#如果您的数据格式是非标准的JSON格式,可以自定义Parser,默认为按照Json方式解析
ydb.reader.parser.class.kafka_json: "cn.net.ycloud.ydb.server.reader.JsonParser"
kafka.topic.kafka_json: "kafkaydb"
kafka.group.kafka_json: "kafkaydb_group"
bootstrap.servers.kafka_json: "192.168.3.2:6667"
3.重启YDB后,10分钟后会开始导入数据
4.Kafka导入的数据格式如下
...... ",\"amt\":8321,\"bank\":\"交通银行\"}"}]}
5.Kafka模式实时导入数据,为什么会有重复数据
YDB能确保从Kafka消费到的数据0丢失,但是由于Kafka的实现机制,以下情况会导致出现重复数据
http://www.iteblog.com/pdf/1716
Kafka采用commitoffset的方式提交数据,由于此时会存在数据已经消费,但是Kafka的offset没有来得及提交,这样会导致数据重复。
如果一个消息已经被消费了,但是还没有提交offset,就开始了Rebalancing,这个时候会造成数据的重复。这个在Kafka里已经积累了一部分数据后的首次启动时最为明显。
如果仅仅发生了一个进程异常退出,但是没有导致Rebalancing,那么最多重复的数据条数就是这个进程还没有来得及提交的部分。
如果发生了Rebalancing(进程异常退出也会导致Rebalancing),那么则要按全部没有来得及提交的线程数来计算。
6.Kafka模式对数据可靠性的几种配置
尽量减少进程重启 导致的数据重复的配置(每个线程32条重复数据)
ydb.realtime.kafka.commit.intervel: 32
ydb.realtime.binlog.sync.intervel: 1024
尽量增加吞吐量的配置, 可能有重复(每个线程1024条重复数据)
ydb.realtime.kafka.commit.intervel: 1024
ydb.realtime.binlog.sync.intervel: 2048
7.多个Kafka Topic一起消费
ydb.reader.list: "default,filesplit,kafka_json,kafka_json2,kafka_json3"
ydb.reader.read.class.kafka_json: "cn.net.ycloud.ydb.server.reader.kafka.KafkaDataReader"
ydb.reader.parser.class.kafka_json: "cn.net.ycloud.ydb.server.reader.JsonParser"
kafka.topic.kafka_json: "a961"
kafka.group.kafka_json: "bn961n_groupv1_kafka_json"
bootstrap.servers.kafka_json: "192.168.3.2:6667"
ydb.reader.read.class.kafka_json2: "cn.net.ycloud.ydb.server.reader.kafka.KafkaDataReader"
ydb.reader.parser.class.kafka_json2: "cn.net.ycloud.ydb.server.reader.JsonParser"
kafka.topic.kafka_json2: "b961"
kafka.group.kafka_json2: "bn961n_groupv1_kafka_json2"
bootstrap.servers.kafka_json2: "192.168.3.2:6667"
ydb.reader.read.class.kafka_json3: "cn.net.ycloud.ydb.server.reader.kafka.KafkaDataReader"
ydb.reader.parser.class.kafka_json3: "cn.net.ycloud.ydb.server.reader.JsonParser"
kafka.topic.kafka_json3: "c961"
kafka.group.kafka_json3: "bn961n_groupv1_kafka_json3"
bootstrap.servers.kafka_json3: "192.168.3.2:6667"
十一、通过mdrill提升简单查询的查询速度
默认简单SQL通过mdrill来执行这个功能是关闭的,大家可以通过下述方式,将一个简单SQL转换为mdrill查询。
1.通过统一配置
可以在ydb_site.yaml里配置 ydb.sql.ismdrill.first的值为true,让ydb系统自动选择是使用mdrill来进行查询还是使用spark调度来执行SQL。
通过该配置,数据明细查询、排序,以及不含有group by的统计会通过mdrill查询。
group by由于mdrill的一万个group 的限制,该方式不会启用。
2.通过ydb_force_to_mdrill_mark让SQL以mdrill的方式显示执行
如果ydb.sql.ismdrill.first为false,不会使用mdrill的调度,但如果我们在SQL加上该标记,就会强制该SQL采用mdrill的调度,而不是采用spark的调度。
3.通过ydb_force_to_spark_mark让SQL以spark的方式执行
转载于:https://www.cnblogs.com/hd-zg/p/7115112.html
YDB基本使用详解(转)相关推荐
- python笛卡尔坐标系_THREE笛卡尔右手坐标系详解
1,正常的笛卡尔右手坐标系,以屏幕右方为+X轴,屏幕上方为+Y轴,垂直屏幕向外为+Z轴,如下图,xy轴组成的平面为屏幕面 但由于THREE里的相机并不总是从屏幕正前方视角,还可以设置坐标系任意一个轴为 ...
- 从命令行到IDE,版本管理工具Git详解(远程仓库创建+命令行讲解+IDEA集成使用)
首先,Git已经并不只是GitHub,而是所有基于Git的平台,只要在你的电脑上面下载了Git,你就可以通过Git去管理"基于Git的平台"上的代码,常用的平台有GitHub.Gi ...
- JVM年轻代,老年代,永久代详解
秉承不重复造轮子的原则,查看印象笔记分享连接↓↓↓↓ 传送门:JVM年轻代,老年代,永久代详解 速读摘要 最近被问到了这个问题,解释的不是很清晰,有一些概念略微模糊,在此进行整理和记录,分享给大家.在 ...
- docker常用命令详解
docker常用命令详解 本文只记录docker命令在大部分情境下的使用,如果想了解每一个选项的细节,请参考官方文档,这里只作为自己以后的备忘记录下来. 根据自己的理解,总的来说分为以下几种: Doc ...
- 通俗易懂word2vec详解词嵌入-深度学习
https://blog.csdn.net/just_so_so_fnc/article/details/103304995 skip-gram 原理没看完 https://blog.csdn.net ...
- 深度学习优化函数详解(5)-- Nesterov accelerated gradient (NAG) 优化算法
深度学习优化函数详解系列目录 深度学习优化函数详解(0)– 线性回归问题 深度学习优化函数详解(1)– Gradient Descent 梯度下降法 深度学习优化函数详解(2)– SGD 随机梯度下降 ...
- CUDA之nvidia-smi命令详解---gpu
nvidia-smi是用来查看GPU使用情况的.我常用这个命令判断哪几块GPU空闲,但是最近的GPU使用状态让我很困惑,于是把nvidia-smi命令显示的GPU使用表中各个内容的具体含义解释一下. ...
- Bert代码详解(一)重点详细
这是bert的pytorch版本(与tensorflow一样的,这个更简单些,这个看懂了,tf也能看懂),地址:https://github.com/huggingface/pytorch-pretr ...
- CRF(条件随机场)与Viterbi(维特比)算法原理详解
摘自:https://mp.weixin.qq.com/s/GXbFxlExDtjtQe-OPwfokA https://www.cnblogs.com/zhibei/p/9391014.html C ...
最新文章
- 8.4 matlab用户界面设计工具
- 本地日志数据实时接入到hadoop集群的数据接入方案
- 窥探Swift之需要注意的基本运算符和高级运算符
- 嵌入式操作系统内核原理和开发(固定内存分配算法)
- i59400f能带动2070s吗?
- 遇到IIS configuration error错误的可以看看,不一定是权限问题
- 使用pyqt开发gui(pyqt集成到pycharm)
- 地区与地区编码的相互转换
- matlab实现3维测井曲线绘制
- ChinaITLab-Linux工程师培训课程笔记7
- ROS机器人开机自启动设置
- 【用户画像和用户标签】
- 应对双11挑战,阿里巴巴智能化运维体系演进与建设
- @iptables防火墙详解
- 服务器维护之后大角会刷新吗,魔兽世界大角刷新最具体时间 准确率达95%
- JDK17 ReentrantLock 简述 lock()、unLock()
- 2018VR一体机VR眼镜哪个牌子好?大家都选了UGP VR眼镜,UGP VR一体机
- DVWA-master通关教程
- 【Markdown】markdown语法规定
- 黎明杀机无限连接服务器错误,更新黎明杀机时发生错误 无法连接到更新服务器 | 手游网游页游攻略大全...
热门文章
- java修改文件名renameTo方法
- IDE与编译器、编辑器的区别
- 全面概括供应链商业保理2020发展趋势
- ubuntu1804下pppoe[有线宽带虚拟拨号]设置
- 基于SSM的校园闲置物品交换系统Java校园二手商城系统的设计与实现(源码调试+讲解+文档)
- 凌玮科技在创业板上市:市值突破47亿元,综合毛利率下滑
- 阿里云-默认封禁TCP 25端口出方向的访问流量,即您无法在阿里云上的云服务器通过TCP 25端口连接外部地址。
- 雷击模型 Matlab/simulink 可用于模拟雷击引起的电能质量问题,可调脉冲电压幅值和发生时间,适配于本家的IEEE 33节点等模型
- 千亿身价之后,美团、拼多多的新增量之战
- 当时来美团我确实很犹豫:阿里很好,团购很乱。