第十章YDB进阶使用详解
一、Lucene原生查询语法的使用
YDB的索引本质上是Lucene索引,如果之前有使用Solr Cloud、ElasticSearch的朋友肯定对Lucene不陌生,对于Lucene有自己的强大的过滤筛选方式,YDB里面依然兼容这种语法方式。
1.使用ydb_raw_query_s like 进行Lucene语法匹配
示例:
ydb_raw_query_s like 'cardnum:9612880118617710'
使用临近搜索的示例
ydb_raw_query_s like 'content:"建设银行"~0'
2.使用ydb_code_query_s like 进行Lucene语法匹配
ydb_raw_query_s与ydb_code_query_s的区别是ydb_code_query_s里的值要进行urlencode编码
如:
ydb_code_query_s like 'content%3A%22%E5%BB%BA%E8%AE%BE%E9%93%B6%E8%A1%8C%22%7E0'
二、自定义拓展分词类型
默认YDB提供了一些分词的数据类型,可以满足大部分的匹配场景,但是如果因为业务的特殊,我们需要自己对Lucene分词进行拓展,YDB也提供了拓展自定义分词的方式。具体使用方法跟Solr的schema.xml非常类似。
1.首先 编辑lib下的fieldType.txt文件,增加新的分词类型
2.然后将相关依赖的jar包放到ydb的lib目录下,并重启YDB
3.建表示例
create table myntest(
c1 ft_yanniantest_y,
c2 ft_yanniantest_yy,
c3 ft_yanniantest_yyy,
c4 ft_yanniantest_yn,
c5 ft_yanniantest_yny,
c6 ft_yanniantest_yyyyyyy,
c7 ft_yanniantest_ynynyny
)
对应关系如下
三、IK词库分词
YDB内置了第三方的IK词库分词,IK分词的介绍如下
1.IKAnalyzer 简介
IKAnalyzer 是一个开源基于 JAVA 语言的轻量级的中文分词第三方工具包,从 2006 年推出已经经历了三个较为完整的版本,目前最新版本为3.2.8,它基于Lucene 为应用主体,但是也支持脱离Lucene,成为一个独立的面向JAVA 的分词工具。
2.IKAnalyzer 特性
a. 算法采用“正向迭代最细粒度切分算法”, 支持细粒度和最大词长两种分词方式,速度最大支持 80W 字/秒(1600KB/秒) 。
b. 支持多子处理器分析模式:中文、数字、字母,并兼容日文、韩文。
c. 较小的内存占用,优化词库占有空间,用户可自定义扩展词库。 采用歧义分析算法优化查询关键字的搜索排列组
d. 扩展Lucene 的扩展实现,
3.YDB内的IK数据类型
textik、ikyy 存储,并且采用IK进行分词
ikyn,只进行IK分词,但不进行存储
4.IK分词的词库,怎样拓展
IK词库文件位于lib目录下的IK_ext.dic
大家修改后,记得重启YDB,以便让词库生效。
四、动态列,动态字段
跟Solr 一样,正常情况下,需要事先把知道的字段定义在创建表中创建好,但是有的时候某个表的字段会不确定,并没同一个表的不同行之间有可能使用的字段也会不同,这时可以使用动态字段。
这是一段动态字段的配置示例:
<dynamicField name="*_s" type="string" indexed="true" stored="false" docValues="true" omitNorms="true" omitTermFreqAndPositions="true" />
这样,送过来的索引数据中,如果有以 _s 结尾的字段的值都都会被按照上述的索引方式进行索引,如字段名称为title_s,content_s。
在匹配过程,如果动态字段和静态字段都符合,会优先匹配静态字段。另外动态字段的仅支持 * 这一通配符,这个通配符仅能位于开头或结尾。
动态字段(Dynamic fields)允许 YDB 索引没有在 create table 中明确定义的字段。这个在忘记定义一些字段时很有用。动态字段可以让系统更灵活,通用性更强。
动态字段和成规字段类似,除了它名字中包含一个通配符外,在索引文档时,一个字段如果在常规字段中没有匹配时,将到动态字段中匹配。
假设schema中定义了一个叫*_i的动态动态字段,如果要索引一个叫 cost_i 的字段,但是 schema 中不存在 cost_i 的字段,这样 cost_i 将被索引到 *_i 字段中。
动态字段也是定义在 schema.xml 文件中,和其他字段一样,它也有个名词,字段类型,和属性。
5.动态字段的配置解析
<dynamicField name="*_s" type="string" indexed="true" stored="false" docValues="true" omitNorms="true" omitTermFreqAndPositions="true" />
1)name="*_s" 匹配规则
2)type="string" 该动态字段 匹配的Solr的fieldType(记住,并不是YDB的数据类型,后面我们会列出默认YDB内部支持的Solr的fieldType,当然也可以通过《自定义拓展分词类型》对于分词的类型进行自定义拓展)
3)indexed="true" 是否启用索引,如果启用该字段可以用于where中的检索
4)stored="false" 其否启用行存储,一般除了分词的类型使用按行存储外,其他的类型均建议按列存储
5)docValues="true"其否启用列存储,一般除了分词的类型使用按行存储外,其他的类型均建议按列存储
6)omitNorms="true" 是否对字段的长度进行规范化,一般我们用不上,建议配置为true直接忽略
7)omitTermFreqAndPositions="true" 对于保存了位置的分词类型,通过这个参数可以配置该字段是否需要保存词频和位置,一般我们都设置为true,不启用。
6.YDB内部支持的solr的fieldType
1)string类型
<fieldType name="string" class="solr.StrField" sortMissingLast="true" omitNorms="true" omitTermFreqAndPositions="true" />
2)int类型
<fieldType name="int" class="solr.TrieIntField" precisionStep="0" positionIncrementGap="0" omitNorms="true" omitTermFreqAndPositions="true" />
3)float类型
<fieldType name="float" class="solr.TrieFloatField" precisionStep="0" positionIncrementGap="0" omitNorms="true" omitTermFreqAndPositions="true" />
4)long类型
<fieldType name="long" class="solr.TrieLongField" precisionStep="0" positionIncrementGap="0" omitNorms="true" omitTermFreqAndPositions="true" />
5)double类型
<fieldType name="double" class="solr.TrieDoubleField" precisionStep="0" positionIncrementGap="0" omitNorms="true" omitTermFreqAndPositions="true" />
6)tint类型
<fieldType name="tint" class="solr.TrieIntField" precisionStep="8" positionIncrementGap="0" omitNorms="true" omitTermFreqAndPositions="true" />
7)tfloat类型
<fieldType name="tfloat" class="solr.TrieFloatField" precisionStep="8" positionIncrementGap="0" omitNorms="true" omitTermFreqAndPositions="true" />
8)tlong类型
<fieldType name="tlong" class="solr.TrieLongField" precisionStep="8" positionIncrementGap="0" omitNorms="true" omitTermFreqAndPositions="true" />
9)tdouble类型
<fieldType name="tdouble" class="solr.TrieDoubleField" precisionStep="8" positionIncrementGap="0" omitNorms="true" omitTermFreqAndPositions="true" />
10)多值列的string类型
<fieldType name="mstring" class="solr.StrField" sortMissingLast="true" omitNorms="true" omitTermFreqAndPositions="true" multiValued="true" />
11)多值列的int类型
<fieldType name="mint" class="solr.TrieIntField" precisionStep="0" positionIncrementGap="0" multiValued="true" omitNorms="true" omitTermFreqAndPositions="true" />
12)多值列的float类型
<fieldType name="mfloat" class="solr.TrieFloatField" precisionStep="0" positionIncrementGap="0" multiValued="true" omitNorms="true" omitTermFreqAndPositions="true" />
13)多值列的long类型
<fieldType name="mlong" class="solr.TrieLongField" precisionStep="0" positionIncrementGap="0" multiValued="true" omitNorms="true" omitTermFreqAndPositions="true" />
14)多值列的double类型
<fieldType name="mdouble" class="solr.TrieDoubleField" precisionStep="0" positionIncrementGap="0" multiValued="true" omitNorms="true" omitTermFreqAndPositions="true" />
15)多值列的tint类型
<fieldType name="mtint" class="solr.TrieIntField" precisionStep="8" positionIncrementGap="0" multiValued="true" omitNorms="true" omitTermFreqAndPositions="true" />
16)多值列的tfloat类型
<fieldType name="mtfloat" class="solr.TrieFloatField" precisionStep="8" positionIncrementGap="0" multiValued="true" omitNorms="true" omitTermFreqAndPositions="true" />
17)多值列的tlong类型
<fieldType name="mtlong" class="solr.TrieLongField" precisionStep="8" positionIncrementGap="0" multiValued="true" omitNorms="true" omitTermFreqAndPositions="true" />
18)多值列的tdouble类型
<fieldType name="mtdouble" class="solr.TrieDoubleField" precisionStep="8" positionIncrementGap="0" multiValued="true" omitNorms="true" omitTermFreqAndPositions="true" />
19)geopoint用于地理位置存储的类型
<fieldType name="geopoint" class="solr.TrieLongField" precisionStep="9" positionIncrementGap="0" multiValued="true" omitNorms="true" omitTermFreqAndPositions="true" />
20)采用cjk二元分词的分词类型
<fieldType name="textcjk" class="solr.TextField" positionIncrementGap="100" omitNorms="true" omitTermFreqAndPositions="true" >
<analyzer type="index">
<tokenizer class="org.apache.lucene.analysis.standard.StandardTokenizerFactory"/>
<filter class="org.apache.lucene.analysis.cjk.CJKWidthFilterFactory"/>
<filter class="org.apache.lucene.analysis.core.LowerCaseFilterFactory"/>
<filter class="org.apache.lucene.analysis.cjk.CJKBigramFilterFactory" />
</analyzer>
<analyzer type="query">
<tokenizer class="org.apache.lucene.analysis.standard.StandardTokenizerFactory"/>
<filter class="org.apache.lucene.analysis.cjk.CJKWidthFilterFactory"/>
<filter class="org.apache.lucene.analysis.core.LowerCaseFilterFactory"/>
<filter class="org.apache.lucene.analysis.cjk.CJKBigramFilterFactory" />
</analyzer>
</fieldType>
21)YDB内置的采用按照字符char方式分词的号码类型
<fieldType name="haoma" class="solr.TextField" omitNorms="true" omitTermFreqAndPositions="true" >
<analyzer type="index">
<tokenizer class="cn.net.ycloud.ydb.tokenizer.ChepaiFactory" maxTokenLength="5" minTokenLength="3" isforsearch="false" />
</analyzer>
<analyzer type="query">
<tokenizer class="cn.net.ycloud.ydb.tokenizer.ChepaiFactory" maxTokenLength="5" minTokenLength="3" isforsearch="true" />
</analyzer>
</fieldType>
22)YDB内置的常规文本分词类型
<fieldType name="simpletext" class="solr.TextField" omitNorms="true" omitTermFreqAndPositions="true" >
<analyzer type="index">
<tokenizer class="cn.net.ycloud.ydb.tokenizer.SimpleTextFactory" maxTokenLength="3" minTokenLength="1" isforsearch="false" />
</analyzer>
<analyzer type="query">
<tokenizer class="cn.net.ycloud.ydb.tokenizer.SimpleTextFactory" maxTokenLength="3" minTokenLength="1" isforsearch="true" />
</analyzer>
</fieldType>
23) YDB内置的保存了词的存储位置信息的,按照字符char方式分词的号码类型
<fieldType name="haomaposition" class="solr.TextField" omitNorms="true" omitTermFreqAndPositions="false" omitPositions="false">
<analyzer type="index">
<tokenizer class="cn.net.ycloud.ydb.tokenizer.ChepaiFactory" maxTokenLength="5" minTokenLength="3" isforsearch="false" />
</analyzer>
<analyzer type="query">
<tokenizer class="cn.net.ycloud.ydb.tokenizer.ChepaiFactory" maxTokenLength="5" minTokenLength="3" isforsearch="true" />
</analyzer>
</fieldType>
24) YDB内置的保存了词的存储位置信息的,普通文本分词
<fieldType name="simpletextposition" class="solr.TextField" omitNorms="true" omitTermFreqAndPositions="false" omitPositions="false" >
<analyzer type="index">
<tokenizer class="cn.net.ycloud.ydb.tokenizer.SimpleTextFactory" maxTokenLength="3" minTokenLength="1" isforsearch="false" />
</analyzer>
<analyzer type="query">
<tokenizer class="cn.net.ycloud.ydb.tokenizer.SimpleTextFactory" maxTokenLength="3" minTokenLength="1" isforsearch="true" />
</analyzer>
</fieldType>
25) YDB内置的保存了词的位置的以及分词的时候保存了多远分词的元长度的,按照按照字符char方式分词的号码类型
<fieldType name="charlike" class="solr.TextField" omitNorms="true" omitTermFreqAndPositions="false" omitPositions="false">
<analyzer type="index">
<tokenizer class="cn.net.ycloud.ydb.tokenizer.ChepaiFactory" ismaketag="true" maxTokenLength="5" minTokenLength="1" isforsearch="false" />
</analyzer>
<analyzer type="query">
<tokenizer class="cn.net.ycloud.ydb.tokenizer.ChepaiFactory" ismaketag="true" maxTokenLength="5" minTokenLength="1" isforsearch="true" />
</analyzer>
</fieldType>
26) YDB内置的保存了词的位置的以及分词的时候保存了多远分词的元长度的,按照按照字符char方式分词的常规文本类型
<fieldType name="wordlike" class="solr.TextField" omitNorms="true" omitTermFreqAndPositions="false" omitPositions="false" >
<analyzer type="index">
<tokenizer class="cn.net.ycloud.ydb.tokenizer.SimpleTextFactory" ismaketag="true" maxTokenLength="3" minTokenLength="1" isforsearch="false" />
</analyzer>
<analyzer type="query">
<tokenizer class="cn.net.ycloud.ydb.tokenizer.SimpleTextFactory" ismaketag="true" maxTokenLength="3" minTokenLength="1" isforsearch="true" />
</analyzer>
</fieldType>
27) 第三方的采用字段词库的IK分词
<fieldType name="textik" class="solr.TextField" omitNorms="true" omitTermFreqAndPositions="true" >
<analyzer type="index">
<tokenizer class="org.wltea.analyzer.lucene.IKTokenizerFactory" useSmart="false" />
</analyzer>
<analyzer type="query">
<tokenizer class="org.wltea.analyzer.lucene.IKTokenizerFactory" useSmart="true" />
</analyzer>
</fieldType>
28) 保存了词的位置的 cjk二元分词
<fieldType name="ptextcjk" class="solr.TextField" positionIncrementGap="100" omitNorms="true" omitTermFreqAndPositions="false" omitPositions="false" >
<analyzer type="index">
<tokenizer class="org.apache.lucene.analysis.standard.StandardTokenizerFactory"/>
<filter class="org.apache.lucene.analysis.cjk.CJKWidthFilterFactory"/>
<filter class="org.apache.lucene.analysis.core.LowerCaseFilterFactory"/>
<filter class="org.apache.lucene.analysis.cjk.CJKBigramFilterFactory" />
</analyzer>
<analyzer type="query">
<tokenizer class="org.apache.lucene.analysis.standard.StandardTokenizerFactory"/>
<filter class="org.apache.lucene.analysis.cjk.CJKWidthFilterFactory"/>
<filter class="org.apache.lucene.analysis.core.LowerCaseFilterFactory"/>
<filter class="org.apache.lucene.analysis.cjk.CJKBigramFilterFactory" />
</analyzer>
</fieldType>
29) lucene默认的文本分词
<fieldType name="text" class="solr.TextField" positionIncrementGap="100" omitNorms="true" omitTermFreqAndPositions="true" >
<analyzer type="index">
<tokenizer class="org.apache.lucene.analysis.standard.StandardTokenizerFactory"/>
<filter class="org.apache.lucene.analysis.core.LowerCaseFilterFactory"/>
</analyzer>
<analyzer type="query">
<tokenizer class="org.apache.lucene.analysis.standard.StandardTokenizerFactory"/>
<filter class="org.apache.lucene.analysis.core.LowerCaseFilterFactory"/>
</analyzer>
</fieldType>
30) 采用lucene默认的文本分词,但保存了词的位置的类型
<fieldType name="ptext" class="solr.TextField" positionIncrementGap="100" omitNorms="true" omitTermFreqAndPositions="false" omitPositions="false" >
<analyzer type="index">
<tokenizer class="org.apache.lucene.analysis.standard.StandardTokenizerFactory"/>
<filter class="org.apache.lucene.analysis.core.LowerCaseFilterFactory"/>
</analyzer>
<analyzer type="query">
<tokenizer class="org.apache.lucene.analysis.standard.StandardTokenizerFactory"/>
<filter class="org.apache.lucene.analysis.core.LowerCaseFilterFactory"/>
</analyzer>
</fieldType>
7.YDB内置的动态字段
1)常规类型的内置定义
<dynamicField name="*_syn" type="string" indexed="true" stored="false" docValues="true" omitNorms="true" omitTermFreqAndPositions="true" />
<dynamicField name="*_iyn" type="int" indexed="true" stored="false" docValues="true" omitNorms="true" omitTermFreqAndPositions="true" />
<dynamicField name="*_lyn" type="long" indexed="true" stored="false" docValues="true" omitNorms="true" omitTermFreqAndPositions="true" />
<dynamicField name="*_fyn" type="float" indexed="true" stored="false" docValues="true" omitNorms="true" omitTermFreqAndPositions="true" />
<dynamicField name="*_dyn" type="double" indexed="true" stored="false" docValues="true" omitNorms="true" omitTermFreqAndPositions="true" />
<dynamicField name="*_tyy" type="text" indexed="true" stored="true" multiValued="true" omitNorms="true" omitTermFreqAndPositions="true" />
<dynamicField name="*_pyy" type="ptext" indexed="true" stored="true" multiValued="true" omitNorms="true" omitTermFreqAndPositions="true" />
<dynamicField name="*_ptyy" type="ptext" indexed="true" stored="true" multiValued="true" omitNorms="true" omitTermFreqAndPositions="false" />
<dynamicField name="*_syy" type="string" indexed="true" stored="false" docValues="true" omitNorms="true" omitTermFreqAndPositions="true" />
<dynamicField name="*_iyy" type="int" indexed="true" stored="false" docValues="true" omitNorms="true" omitTermFreqAndPositions="true" />
<dynamicField name="*_lyy" type="long" indexed="true" stored="false" docValues="true" omitNorms="true" omitTermFreqAndPositions="true" />
<dynamicField name="*_fyy" type="float" indexed="true" stored="false" docValues="true" omitNorms="true" omitTermFreqAndPositions="true" />
<dynamicField name="*_dyy" type="double" indexed="true" stored="false" docValues="true" omitNorms="true" omitTermFreqAndPositions="true" />
<dynamicField name="*_sny" type="string" indexed="false" stored="true" docValues="false" omitNorms="true" omitTermFreqAndPositions="true" />
<dynamicField name="*_iny" type="int" indexed="false" stored="true" docValues="false" omitNorms="true" omitTermFreqAndPositions="true" />
<dynamicField name="*_lny" type="long" indexed="false" stored="true" docValues="false" omitNorms="true" omitTermFreqAndPositions="true" />
<dynamicField name="*_fny" type="float" indexed="false" stored="true" docValues="false" omitNorms="true" omitTermFreqAndPositions="true" />
<dynamicField name="*_dny" type="double" indexed="false" stored="true" docValues="false" omitNorms="true" omitTermFreqAndPositions="true" />
<dynamicField name="*_sdt" type="string" indexed="true" stored="false" docValues="true" omitNorms="true" omitTermFreqAndPositions="true" />
<dynamicField name="*_sdtms" type="string" indexed="true" stored="false" docValues="true" omitNorms="true" omitTermFreqAndPositions="true" />
<dynamicField name="*_sdtns" type="string" indexed="true" stored="false" docValues="true" omitNorms="true" omitTermFreqAndPositions="true" />
<dynamicField name="*_s" type="string" indexed="true" stored="false" docValues="true" omitNorms="true" omitTermFreqAndPositions="true" />
<dynamicField name="*_i" type="int" indexed="true" stored="false" docValues="true" omitNorms="true" omitTermFreqAndPositions="true" />
<dynamicField name="*_l" type="long" indexed="true" stored="false" docValues="true" omitNorms="true" omitTermFreqAndPositions="true" />
<dynamicField name="*_f" type="float" indexed="true" stored="false" docValues="true" omitNorms="true" omitTermFreqAndPositions="true" />
<dynamicField name="*_d" type="double" indexed="true" stored="false" docValues="true" omitNorms="true" omitTermFreqAndPositions="true" />
<dynamicField name="*_ii" type="int" indexed="false" stored="false" docValues="true" omitNorms="true" omitTermFreqAndPositions="true" />
<dynamicField name="*_ll" type="long" indexed="false" stored="false" docValues="true" omitNorms="true" omitTermFreqAndPositions="true" />
<dynamicField name="*_ff" type="float" indexed="false" stored="false" docValues="true" omitNorms="true" omitTermFreqAndPositions="true" />
<dynamicField name="*_dd" type="double" indexed="false" stored="false" docValues="true" omitNorms="true" omitTermFreqAndPositions="true" />
2)多值列的内置定义
<dynamicField name="*_mf" type="mfloat" indexed="true" stored="false" docValues="true" multiValued="true" omitNorms="true" omitTermFreqAndPositions="true" />
<dynamicField name="*_mff" type="mfloat" indexed="false" stored="false" docValues="true" multiValued="true" omitNorms="true" omitTermFreqAndPositions="true" />
<dynamicField name="*_md" type="mdouble" indexed="true" stored="false" docValues="true" multiValued="true" omitNorms="true" omitTermFreqAndPositions="true" />
<dynamicField name="*_mdd" type="mdouble" indexed="false" stored="false" docValues="true" multiValued="true" omitNorms="true" omitTermFreqAndPositions="true" />
<dynamicField name="*_ml" type="mlong" indexed="true" stored="false" docValues="true" multiValued="true" omitNorms="true" omitTermFreqAndPositions="true" />
<dynamicField name="*_mll" type="mlong" indexed="false" stored="false" docValues="true" multiValued="true" omitNorms="true" omitTermFreqAndPositions="true" />
<dynamicField name="*_mi" type="mint" indexed="true" stored="false" docValues="true" multiValued="true" omitNorms="true" omitTermFreqAndPositions="true" />
<dynamicField name="*_mii" type="mint" indexed="false" stored="false" docValues="true" multiValued="true" omitNorms="true" omitTermFreqAndPositions="true" />
3)分词类型的内置定义
<dynamicField name="*_tyn" type="text" indexed="true" stored="false" multiValued="true" omitNorms="true" omitTermFreqAndPositions="true" />
<dynamicField name="*_tny" type="text" indexed="false" stored="true" multiValued="true" omitNorms="true" omitTermFreqAndPositions="true" />
<dynamicField name="*_txt" type="text" indexed="true" stored="false" multiValued="true" omitNorms="true" omitTermFreqAndPositions="true" />
<dynamicField name="*_ytext" type="simpletext" indexed="true" stored="true" multiValued="true" omitNorms="true" omitTermFreqAndPositions="true" />
<dynamicField name="*_ytextsearch" type="simpletext" indexed="true" stored="false" multiValued="true" omitNorms="true" omitTermFreqAndPositions="true" />
<dynamicField name="*_yhaoma" type="haoma" indexed="true" stored="true" multiValued="true" omitNorms="true" omitTermFreqAndPositions="true" />
<dynamicField name="*_yhaomasearch" type="haoma" indexed="true" stored="false" multiValued="true" omitNorms="true" omitTermFreqAndPositions="true" />
<dynamicField name="*_ychepai" type="chepai" indexed="true" stored="true" multiValued="true" omitNorms="true" omitTermFreqAndPositions="true" />
<dynamicField name="*_ychepaisearch" type="chepai" indexed="true" stored="false" multiValued="true" omitNorms="true" omitTermFreqAndPositions="true" />
4)分词类型并且存储了位置的内置定义
<dynamicField name="*_pyn" type="ptext" indexed="true" stored="false" multiValued="true" omitNorms="true" omitTermFreqAndPositions="true" />
<dynamicField name="*_ptyn" type="ptext" indexed="true" stored="false" multiValued="true" omitNorms="true" omitTermFreqAndPositions="false" />
<dynamicField name="*_pny" type="ptext" indexed="false" stored="true" multiValued="true" omitNorms="true" omitTermFreqAndPositions="true" />
8.自定义拓展新的动态列
大家可以编辑lib目录下的dynamicField.txt文件,添加自己的动态列,写法同上。
编辑完毕后,要重启YDB。
五、利用Spoon的Kattle将传统数据库的数据导入到YDB中
1.拷贝JDBC驱动包(oracle):
data-integration\lib
ojdbc6.jar
2.拷贝Hadoop配置文件(ydbmaster)
data-integration\plugins\pentaho-big-data-plugin\hadoop-configurations\hdp24(ydbmaster)
core-site.xml
hdfs-site.xml
yarn-site.xml
mapred-site.xml
3.设置HDP插件版本
4.创建YDB表
5.创建Hive外部表
6. 创建 Spoon 转换项目
7.插入表输入模块
8.插入Hadoop File Output 模块
9.插入阻塞数据模块
10.插入执行SQL脚本模块
11.运行并显示结果
六、如何利用Sqoop将传统数据库的数据导入到YDB中
Sqoop本质上是一个ETL工具,可以将传统数据里面的数据,导出到 HDFS中,然后通过Hive表就可以将数据导入到YDB中
1.Sqoop导出到HDFS基本的Oracle示例如下
sqoop import --connect jdbc:oracle:thin:@xx.xx.xx.xx:1521:xxxdb --username 用户名 --password密码 --query "selectc1,c2,xxxx,xxx from 数据表 where \$CONDITIONS " --target-dir /data/sqoop/oracle表名/$vardate --input-null-string '\\N' --input-null-non-string '\\N' --split-by id --fields-terminated-by '\001' -m 1
2.我给客户写的一个同步的小shell程序
#!/usr/bin/env bash
vardate="ydb_default_partion"
varmonth="ydb_default_partion"
echo $vardate
echo $varmonth
#----step one ---
echo "begin step one"
hadoop fs -mkdir -p /data/sqoop/table_exampel/$vardate
hadoop fs -rm -r /data/sqoop/table_exampel/$vardate
sqoop import --connect jdbc:sap://10.36.11.108:30015 --driver com.sap.db.jdbc.Driver --username oracleUser --password oraclepasswd --query "select * FROM oracle_table_name WHERE \$CONDITIONS" --target-dir /data/sqoop/table_exampel/$vardate --split-by xh --fields-terminated-by '\001' -m 1
#----step two ---
echo "begin step two"
echo "plaase create table_exampel_txt on hive first "
echo "ALTER TABLE table_exampel_txt DROP IF EXISTS PARTITION (event_day='$vardate'); " > /ydb/daoru.sql
echo "ALTER TABLE table_exampel_txt ADD IF NOT EXISTS PARTITION (event_day='$vardate') LOCATION '/data/sqoop/table_exampel/$vardate'; " >> /ydb/daoru.sql
echo "select * from table_exampel_txt where event_day='$vardate'; " >> /ydb/daoru.sql
sh /opt/ydbsoftware/ya100/bin/sql.sh -f /ydb/daoru.sql
#----step three ---
echo "begin step three"
cat << EOF >/ydb/daoru.sql
insert into table ydbpartion
select 'table_exampel', '$varmonth', '',
YROW(
'ID',ID,
'xxx1',xx1,
'xx2',xx2,
'FLAG',FLAG
)
from table_exampel_txt where event_day='$vardate';
/*ydb.pushdown('->')*/
select count(*) from table_exampel where ydbpartion = "$varmonth"
/*('<-')pushdown.ydb*/
EOF
sh /opt/ydbsoftware/ya100/bin/sql.sh -f /ydb/daoru.sql
echo "execute finished"
七、如何将HBase中的数据导入到YDB里
默认Hive提供了与HBase对接的API,但是放在了Spark中兼容性不是特别好。YDB修改了这个地方,以便为了能让其运行,但是实测性能一般。
1.通过Spark可以与HBase进行连接,
这样就可以方便的将数据从HBase中导入到Ydb中了
具体原理参考http://www.tuicool.com/articles/N36Brm
l第1步,复制相关依赖的jar包到ya100的lib目录下(注意,这里极容易产生jar包冲突,比如hive与hbase版本不匹配)
如:
$HIVE_HOME/lib/hive-hbase-handler-0.13.1.jar
$HBASE_HOME/lib/hbase-client-0.96.1.1-cdh5.0.0.jar
$HBASE_HOME/lib/hbase-common-0.96.1.1-cdh5.0.0.jar
$HBASE_HOME/lib/hbase-protocol-0.96.1.1-cdh5.0.0.jar
$HBASE_HOME/lib/hbase-server-0.96.1.1-cdh5.0.0.jar
$HBASE_HOME/lib/htrace-core-2.01.jar
$HBASE_HOME/lib/protobuf-java-2.5.0.jar
$HBASE_HOME/lib/guava-12.0.1.jar
并且 配置环境变量,记得jar包名字别写错了
export SPARK_CLASSPATH=/home/ycloud/ya100/lib/guava-12.0.1.jar:/home/ycloud/ya100/lib/hive-hbase-handler-1.2.1.2.3.4.0-3485.jar:/home/ycloud/ya100/lib/hbase-client.jar:/home/ycloud/ya100/lib/hbase-common.jar:/home/ycloud/ya100/lib/hbase-protocol.jar:/home/ycloud/ya100/lib/hbase-server.jar:/home/ycloud/ya100/lib/htrace-core-3.1.0-incubating.jar:/home/ycloud/ya100/lib/protobuf-java-2.5.0.jar
l第2步,配置HBase的Master地址
将hbase-site.xml 的内容复制到hive-site.xml
l第3步,创建Hive与HBase的连接表(HBase默认的HBaseStorageHandler在Spark下有兼容性的问题,我稍微改了下)
CREATE TABLE hbase_table(
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
)
STORED BY 'cn.net.ycloud.ydb.handle.HBaseStorageHandler_YDB'
WITH SERDEPROPERTIES ("hbase.columns.mapping" = ":key,cf1:usernick,cf1:ydb_sex,cf1:ydb_province,cf1:ydb_grade,cf1:ydb_age,cf1:ydb_blood,cf1:ydb_zhiye,cf1:ydb_earn,cf1:ydb_prefer,cf1:ydb_consume,cf1:ydb_day,cf1:amtdouble,cf1:amtlong,cf1:content")
TBLPROPERTIES ("hbase.table.name" = "hive_hbase_2016");
2.读取HBase中的数据到文本形式的Hive表中
insert overwrite table ydb_example_txt select *,'hbase2ydb',1 from hbase_table;
ps:本质上可以直接导入到YDB中,但是实测发现,这种方式导入的数据,Map数量并不均衡,有比较严重的数据倾斜,性能不好,所以我们不在给出直接导入到YDB中的例子,而是先导到Hive的文本表,然后通过文本表在导入到YDB中
3.从文本表导入到YDB总
使用方法,请参考前文,这里不做重复介绍。
八、YDB系统表,日志表
1.启用系统表
YDB内置日志表,需要通过Kafka来收集消息,如果要启动内部日志表,需要在ydb_site.yaml里配置如下Kafka参数
ydb.reader.ydb_syslog: 'true'
kafka.topic.ydb_syslog: 'ydb_syslog'
bootstrap.servers.ydb_syslog: 'ydbmaster:6667'
2. --数据预览
/*ydb.pushdown('->')*/
select * from y_system_log order by log_time desc
limit 30
/*('<-')pushdown.ydb*/
;
3.--查看最近执行过的SQL(HIVE)
/*ydb.pushdown('->')*/
select log_time,log_day,reqid_syn,timelen_lyn,log_hour,log_category,log_type,log_pos,log_ip,log_pid,log_execid,log_execindex,log_fields,log_hostname,log_msg from y_system_log where log_category='SQL' and (log_type='getExecuteSql') order by reqid_syn desc,log_time desc
limit 30
/*('<-')pushdown.ydb*/
;
4. --按照ID查看特定某一SQL
/*ydb.pushdown('->')*/
select log_time,log_day,reqid_syn,timelen_lyn,log_hour,log_category,log_type,log_pos,log_ip,log_pid,log_execid,log_execindex,log_fields,log_hostname,log_msg from y_system_log where log_category='SQL' and reqid_syn='161204024000000002' order by log_time desc
limit 30
/*('<-')pushdown.ydb*/
;
5. --查看系统报错
/*ydb.pushdown('->')*/
select log_time,log_day,log_hour,log_category,log_type,log_pos,log_ip,log_pid,log_execid,log_execindex,log_fields,log_hostname,log_msg from y_system_log where log_category='ERROR' order by log_time desc
limit 30
/*('<-')pushdown.ydb*/
;
6. --查看系统负载
/*ydb.pushdown('->')*/
select log_time,log_day,log_hour,log_category,log_type,log_pos,log_ip,log_pid,log_execid,log_execindex,log_hostname,os_cpu_user_lyn,os_cpu_nick_lyn,os_cpu_sys_lyn,os_cpu_idle_lyn,os_iowait_lyn,os_steal_lyn,os_mem_total_lyn,os_mem_free_lyn,os_mem_used_lyn,os_mem_buff_lyn,os_mem_cache_lyn from y_system_log where log_category='SYSTEMINFO' order by log_time desc
limit 30
/*('<-')pushdown.ydb*/
;
7. --线程池
/*ydb.pushdown('->')*/
select log_time,log_day,log_hour,log_category,log_type,log_pos,log_ip,log_pid,log_execid,log_execindex,log_fields,log_hostname,log_msg from y_system_log where log_category='POOL' order by log_time desc
limit 30
/*('<-')pushdown.ydb*/
;
8. --统计
/*ydb.pushdown('->')*/
select log_type,count(*) as cnt from y_system_log group by log_type order by cnt desc
limit 30
/*('<-')pushdown.ydb*/
;
/*ydb.pushdown('->')*/
select log_day,count(*) as cnt from y_system_log group by log_day order by cnt desc
limit 30
/*('<-')pushdown.ydb*/
;
/*ydb.pushdown('->')*/
select log_category,count(*) as cnt from y_system_log group by log_category order by cnt desc
limit 30
/*('<-')pushdown.ydb*/
;
/*ydb.pushdown('->')*/
select log_category,log_type,log_pos,count(*) as cnt from y_system_log group by log_category,log_type,log_pos order by cnt desc
limit 30
/*('<-')pushdown.ydb*/
;
九、10万列规模以上的大宽表如何处理?
Hive表并不支持太多的列,对于Oracle来说最多支持1000个列,如果我们的业务有一个将近一万个列的大宽表,应该怎么办?
1.传统做法存在什么问题?
如果我们采用传统做法,直接写一个10万列的create table语句。
l12W列意味着生成的schema文件就要20多m,由于太大,读取这个表的配置一是耗费很多内存,二是解析也很慢。
lLucene内部的列也很多,在打开索引文件的时候,由于要加载列的信息,索引文件的打开会特别慢。
l12w列在Hive表中(Spark 的Hive SQL模式),也意味着占用太多的元数据库信息,而且建表也容易失败,要知道Hadoop的configuration也是有大小限制的。
2.应该如何做?
l数据类型相近的列,经常一起访问的列,推荐分组并合并,YDB内置有多值列,可以用这一个列存储,这一个组内多个不同的值,这样值的个数没有少,但是列数少了很多。更多的请参考多值列的示例。
l有些列可以采用动态列,减少生成的schema.xml的大小。
lya100_env.sh 如下配置都要改,要至少分配20G以上内存
export YA100_MEMORY=25000m
export YA100_DRIVER_MEMORY=15000m
十、使用帆软FineReport生成基于YDB数据的报表
FineReport是由帆软自主研发的一款纯Java编写的报表软件产品,集数据展示(报表)和数据录入(表单)功能于一身,能够制作复杂的报表,操作简单易用。针对软件开发商和系统集成商,用于快速构建企业信息系统的中国式Web报表软件。由于帆软支持jdbc接入,故YDB也可以与帆软集成。
下面为集成的示例:
1.报表类型
2.常用的图表种类
3.首先将HIVE的JDBC驱动Jar包
hive-jdbc-1.2.1-standalone.jar(该jar包可在ydb的libexec中找到)
复制到${FineReport_Home}\WebReport\WEB-INF\lib中
${FineReport_Home}:FineReport的根目录
4.创建JDBC连接
打开菜单:服务器①->定义数据连接②创建一个HIVE的JDBC连接
5.创建数据库连接
点击加号创建一个数据连接①,驱动器栏输入(org.apache.hive.jdbc.HiveDriver)②,
在URL中输入(jdbc:hive2://ydbmaster:10009/default)其中ydbmaster为所要连接的主机域名③,配置完成后点击测试连接,检查是否配置正确④
6.创建一个模板数据集
7.编辑数据集
选择上一步创建的数据库连接①,在白色输入框中写入sql语句,YDB SQL需要使用特殊的标签包裹②而HIVE SQL则不需要,在WHERE条件的开始处添加一条必定为真的条件,例如性别字段中的值不为0③。
使用函数${if(len(字段名) == 0,"默认值或空","and 字段名 = '" + 变量名 + "'")}来设定如果值为空则不查询或查询默认值④,点击刷新⑤会在下方显示设定的参数,可通过修改参数值来向sql中注入查询参数⑥。
在编辑好sql语句之后点击预览来查看sql语句是否能够成功执行⑦。
在⑧处可选择将所有查询结果都存储到内存中,还是当记录数大于定值的时候将剩余数据缓存到磁盘。
示例sql: 注意,帆软值SQL中支持写if模板变量,注意图中加粗的部分
/*ydb.pushdown('->')*/
select ydb_sex,ydb_grade,ydb_age,ydb_blood,amtlong
from ydb_example_shu
where ydb_sex!=0
${if(len(ydbpartion) == 0,"and ydbpartion=\'ydb_default_partion\'","and ydbpartion = '" +ydbpartion + "'")}
${if(len(ydb_sex) == 0,"","and ydb_sex = '" + ydb_sex + "'")}
${if(len(ydb_grade) == 0,"","and ydb_grade = '" + ydb_grade + "'")}
and (ydb_age='20到30岁' or ydb_blood='O')
and (amtlong like '([3000 TO 4000] )')
${if(len(limit) == 0," limit 100 "," limit "+limit+"")}
/*('<-')pushdown.ydb*/
8.编辑模版数据集
1)在上一步中我们设定了四个查询字段参数:ydb_grade,ydb_sex,limit,ydbpartion,在此处我们需要创建相同名称的模板参数来关联它们,点击模板①->模板参数②进入模板参数编辑菜单,
2)点击①添加一个模板参数,双击②修改参数名称,可在③处设置参数的默认值
9.生成查询表单
点击此处编辑查询表单①。
此处是上一步创建的模板参数①,点击”全部添加”②创建对应参数的查询表单
点击此处选择表单框的类型
表单框的类型有很多,此处我们选择‘文本控件’。
10.添加报表类型聚合块
将‘报表类型聚合块’拖拽至报表的空白区域
在图表的第一行输入列名,将数据模板中的数据列拖拽到对应的列名下
拖动右上和左下的灰色块可以调节表的列数和行数①,右下的灰色块可以移动图表的位置②
11.预览
点击左上的笔记本图标下的小箭头①,选择数据分析②
在弹出页面的对应表单中输入查询参数,点击查询
12.添加饼图
将饼图模块拖拽至报表空白区域,点击饼图区域,在屏幕右上角图表属性表区域中选择‘数据’标签页,定义对应的规则
由于报表类型聚合块大小不定,建议将其放在报表的下方
注:柱形图,条形图,折线图的设置方法与饼图相同。
预览
十一、实时消息接入自定义Reader与Parser
YDB支持自定义任意的数据源接入,以及解析任意格式的数据,只需要您实现Reader与Parser的接口
1.Reader需要实现的普通接口
publicinterface RawDataReader
{
publicvoid init(Stringprefix,KVgetconfig,intreaderIndex,intreaderCount)
throws IOException;
public List<Object> read()throws IOException;
publicvoid close()throws IOException;
publicvoid setParser(Parserparser);
}
2.事务性Reader的接口
如果担心进程异常退出,可以进一步实现如下的接口,与binlog结合保证数据不丢失
publicinterface YdbRawDataReaderWithCommitextends YdbRawDataReader
{
public YdbParse Parse(byte[]ahead )throws Throwable;
publiclong walWrite(YdbParsedoclist)throws Throwable;
publicvoid walMayCommit(longmaxcnt,ArrayList<YdbParse>doclist)throws Throwable;
publicvoid process(YdbParsedoclist)throws Throwable;
}
3.Parser需要实现的接口
默认我们只有JSON的Parser,如果我们的数据不是YDB的Json个数,就需要自己实现改接口来拓展
publicinterfaceParser {
public abstractvoid init(Stringprefix,KVgetconfig,
intreaderIndex,intreaderCount)
throws IOException;
publicvoid setReaderMeta(Objectmeta);
public YdbParse parse(Objectraw)throws Throwable;
4.如何使用写好的Reader
1)Reader与Parser实现完成后,将其以jar包的方式放到lib目录下
2)更改ydb_site.xml变更Parser与Reader所指向的类名
3)重启YDB
十二、自定义拓展分词
默认YDB的分词采用Lucene分词,Lucene分词的写法示例如下
集团的内部通讯工具搜同事时,需要根据姓名后缀进行搜索。譬如“徐欢春”,我们要能根据“欢春”搜出这个人;“黄继刚”,要根据“继刚”为关键字搜出“黄继刚”。这是个很人性化的用户体验,当我们有同事的名字是三个字的时候,我们通常会叫他们名字的最后两个字。Lucene本身并没有提供这种分词器,只能自己照着Lucene已有的分词器进行模仿开发。
参照ngram分词器进行开发。
要定制这个后缀分词器,实现一个Tokenizer和一个工厂类就可以了。Tokenizer类是实际分词是要用到的类。为了方便单元测试,额外增加一个Analyzer类。
分词器类
package org.apache.lucene.analysis.suffix;
import java.io.IOException;
import java.io.Reader;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.lucene.analysis.Tokenizer;
import org.apache.lucene.analysis.tokenattributes.CharTermAttribute;
import org.apache.lucene.analysis.tokenattributes.OffsetAttribute;
/**
* 用于姓名取后缀的分词器
*
* @author cdlvsheng
* date : 2014年9月23日
* time : 下午1:49:36
* project : im-solr-web
* user : cdlvsheng
*/
public class SuffixTokenizer extends Tokenizer {
private Log LOG = LogFactory.getLog(SuffixTokenizer.class);
private char[] buffer = new char[1024];
private int suffixOffset;
private static int MAX_SIZE;
private int termSize;
private final CharTermAttribute termAtt = addAttribute(CharTermAttribute.class);
private final OffsetAttribute offsetAtt = addAttribute(OffsetAttribute.class);
protected SuffixTokenizer(Reader input) {
super(input);
}
protected SuffixTokenizer(AttributeFactory factory, Reader input) {
super(factory, input);
}
@Override
public boolean incrementToken() throws IOException {
try {
clearAttributes();
if (termSize != -1) {
termSize = input.read(buffer);
if (termSize >= 0) {
MAX_SIZE = termSize;
}
}
if (suffixOffset + 1 >= MAX_SIZE) {
return false;
}
termAtt.copyBuffer(buffer, suffixOffset, MAX_SIZE);
termAtt.setLength(MAX_SIZE - suffixOffset);
offsetAtt.setOffset(correctOffset(suffixOffset), correctOffset(MAX_SIZE));
LOG.debug(termAtt.buffer());
suffixOffset++;
} catch (Exception e) {
LOG.error(e.getMessage(), e);
}
return true;
}
@Override
public final void end() {
final int finalOffset = correctOffset(suffixOffset);
this.offsetAtt.setOffset(finalOffset, finalOffset);
}
@Override
public void reset() throws IOException {
super.reset();
termSize = 1;
suffixOffset = 1;
MAX_SIZE = 0;
}
}
incrementToken方法是实际分词时用到的方法。一会单元测试时可以看出它的作用。
工厂类
package org.apache.lucene.analysis.suffix;
import java.io.Reader;
import java.util.Map;
import org.apache.lucene.analysis.Tokenizer;
import org.apache.lucene.analysis.util.TokenizerFactory;
import org.apache.lucene.util.AttributeSource.AttributeFactory;
public class SuffixTokenizerFactory extends TokenizerFactory {
public SuffixTokenizerFactory(Map<String, String> args) {
super(args);
}
@Override
public Tokenizer create(AttributeFactory factory, Reader input) {
return new SuffixTokenizer(factory, input);
}
}
工厂类的作用就是产生分词器类的实例。
analyzer类
package org.apache.lucene.analysis.suffix;
import java.io.Reader;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.Tokenizer;
public final class SuffixAnalyzer extends Analyzer {
@Override
protected TokenStreamComponents createComponents(String fieldName, Reader reader) {
final Tokenizer source = new SuffixTokenizer(reader);
return new TokenStreamComponents(source, source);
}
以上3个类合作就构成了一个完整的自定义分词器组件。
单元测试
package test.prefix.tokenizer;
import java.io.IOException;
import org.apache.lucene.analysis.TokenStream;
import org.apache.lucene.analysis.suffix.SuffixAnalyzer;
import org.apache.lucene.analysis.tokenattributes.CharTermAttribute;
import org.junit.Test;
/**
* @author cdlvsheng
* date : 2014年9月22日
* time : 下午7:23:01
* project : im-solr-web
* user : cdlvsheng
*/
public class SuffixTest {
@SuppressWarnings("resource")
@Test
public void suffixTest() {
try {
SuffixAnalyzer analyzer = new SuffixAnalyzer();
TokenStream ts = analyzer.tokenStream("text", "黄继刚");
CharTermAttribute term = ts.addAttribute(CharTermAttribute.class);
ts.reset();
while (ts.incrementToken()) {
System.out.println(term.toString());
}
ts.end();
ts.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
十三、为了OEM自定义YDB UI的header与footer样式
配置参数为
ydb.web.info.header
ydb.web.info.fooder
相关推荐
延云YDB安装与使用说明书 超千亿规模的数据,数据库根本就运行不了,怎么办? 数据从产生到能够查询,要延迟一天才能看到,如何能做到分钟级延迟? 50台规模的hadoop集群,几亿条数据,一个MR任务要运行几小时,每天...
在当今的信息化社会,大数据已经成为了推动科技进步与创新的关键力量,而YDB作为一款重要的数据库系统,正是在这样的背景下脱颖而出,扮演着至关重要的角色。本文将深入探讨YDB在大数据时代的应用、特点以及其对大...
### 延云YDB:万亿数据秒级查询与分析引擎 #### 一、概述 随着信息技术的飞速发展,大数据已经成为推动企业决策、产品创新和业务增长的关键力量。面对日益增长的数据规模和复杂的数据结构,传统的数据分析工具已经...
ydb 是像gdb一样的php调试工具,用扩展实现,可以在运行过程中查看变量值,也可以进行性能测试,而不用对源代码进行任何更改,就像xdebug和xhprof 中提供的功能,但使用更方便 ydb也可以称为一个在线调试工具,...
延云YDB安装与使用说明书 超千亿规模的数据,数据库根本就运行不了,怎么办? 数据从产生到能够查询,要延迟一天才能看到,如何能做到分钟级延迟? 50台规模的hadoop集群,几亿条数据,一个MR任务要运行几小时,...
YDB是我们自主研发的一个大型分布式索引系统。旨在为数据总量为万亿级别、每天千亿级别数据增量的项目提供近似实时的数据导入,并提供近似实时响应的多维查询与统计服务。 大索引技术 为什么要使用大索引?使用后会...
YDB 199-2018 移动互联网+智能家居系统总体要求.pdf
YDB是我们自主研发的一个大型分布式索引系统。旨在为数据总量为万亿级别、每天千亿级别数据增量的项目提供近似实时的数据导入,并提供近似实时响应的多维查询与统计服务。 大索引技术 为什么要使用大索引?使用后会...
YDB144-2014云计算服务协议参考框架
YDB 101-2012 物联网安全需求
YDB全称延云YDB,是一个基于Hadoop分布式架构下的实时的、多维的、交互式的查询、统计、分析引擎,具有万亿数据规模下的秒级性能表现,并具备企业级的稳定可靠表现。 YDB是一个细粒度的索引,精确粒度的索引。数据...
本资料“Java ORM框架和迁移工具的官方YDB方言”可能是关于如何在Java ORM工具中集成和使用YDB特性的详细指南。 1. **Java ORM框架介绍** - Hibernate:是最流行的ORM框架之一,提供了一种在Java应用程序中操作...
YDB 165-2016 面向物联网的蜂窝窄带接入(NB-IoT) 无线网总体技术要求 通信行业的参考标准,规范了通信物联网的蜂窝窄带接入(NB-IOT)网络的架构,规定了物理层,高层,及PRC层的技术要求及移动管理性,本标准使用...
《YDB编程指南》是一本专注于YDB编程的最新版参考书籍,旨在帮助开发者深入了解和掌握YDB这一特定编程语言的使用。YDB可能是一种专为处理大规模数据设计的数据库系统,因此它与大数据处理紧密相关。以下是根据提供的...
php在线调试工具,一个php扩展,适用于php5.2版本 md5: 638e7f30d2f4d25b5ce5128e39e597bf 具体文档介绍见 http://blog.csdn.net/micweaver/article/details/17891163
如何使用 安装依赖和编译库 npm ci npm run build:lib 设置环境变量 不应为特定安装设置的变量显式设置为空值,以便启动脚本正确检测您所针对的安装。 常见变量 export YDB_SDK_LOGLEVEL=debug export IAM_ENDPOINT...