版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
DDB应用开发者白皮书By 一.导 DDB架构简 二.DDBSQL语 过 三.Hint语法说 DIRECT 四.附 DBI接口总 DBI示例程 一.导语DDB作为杭研最老的产品之一,几乎伴随了网易所有大型互联网产品的成长,8帮助众多产品和用户解决了大数据,分库分表的问题。本书目的在于帮助这些产品和用户更快更方便地熟悉并适应基于DDB的应用开发。DDB用户手册,并加以整理。由于手册内容过于详实,不太适合DDB架构基础上,重点记录了DDB的SQL语则(支持什么,不支持什么,便于开发者随时查阅。本书使DDBV4.5.7即以上,老DDBSQL语法上有若BUG和限制,对使用旧版本的开发者,建议在阅读本书之外,对使用的SQL进行充分测试。DDBJDBCDBIDBIStandardjdbc数据节点MySQL数据节点MySQL数据节点MySQL抽象语Result应用层1DBI应用APP通过DDB提供的JDBC驱动DBI(DatabaseInterface)来DDB,就像MySQL应用需要通过提供的JDBC驱动Connection/JMySQL一样。DBI与标准Connection/J不一样的地方在于,Connection/J的功能仅是按照MySQL通信协议将应用SQL提交给MySQLServer执行,SQL的解析和执行均在MySQLServerDBISQL,经过数据节点返回的结果合并后返回给应用APP,SQL:select*fromBlogorderby DBISQLSELECT语法树,DBI执行器根SELECTselect语句下发给每个数据节点,在由于DBI中的语法解析,生成执行计划以及执行器执行都在应用端,会占用应用端一部构建SQLDBISELECT语句这使用DDB提供的JDBC驱动DBIDDB存在一定的缺陷使用DBI需要应用端部署DBI的jar包:db.jar, mons.jar,common.jar等,DDB升级需要与应用沟通重启停服,给运维和升级工作带来,这也直接导致了目前DDB产品线从3.3-4.5都有,给技术支持造成了很大的不便。由于DIDIDI内部了一些文件锁,瞬间重启可能由于操作系统的文件锁没来得及释放而抛异DIDCQueryQueryMySQLMySQLMySQL2QSDDB的这种使用模式中,首先要为应用部署一个或多个查询服务器,查询服务器负责MySQL标准JDBC驱动到DDB的JDBC驱动的转换,应用通过标准JDBCDBISQLMySQL通信协议编码返回给与DBI模块再无关联,而DDB的运维升级也无需应用感知。通过HA的分流机制,还可以做到不停服升级。另外,QSMySQL通信协议交互,真正做到了多语言支持。除此之外,QS还具备以下几点优势:QS的运维命令(showprocesslist等)查看DBI驱动的各种状态,以及QSQS服务器,以及应用请求多次在网络中过度带来的风险,即便如此,QSDDBSLA。因此强烈推荐用户使用QS模式。以实现DDB的一键部署和更好地控制成本。QS的情况可以向DDB开发组寻求技技术支持与反馈 DDBDOC平台:http://d DDBFAQ:http://d 二.DDBSQL语分布式数据库支持常用的SQLDML语句的基本功能。分布式数据库支持的SQL语句简支持UPDATE、DELETE支持简单和复杂的HAVING支持DISTINCT,并可与函数联合使支持支持FORUPDATE、LOCKINSHARE支持支持SELECT在支持多表连接查询时,SQL语句中表的出现顺序进行,UPDATE和DDBSQLDDB开发组。由于旧版本中存在个别语法上的BUG,建议使用DDB稳定版4.5.7。分布式数据库支持单表和多表联接查询,支持SQL标准中定义的GROUPBY/HAVING、ORDERBY、LIMIT/OFFSET等子句的基本功能,另外还支持MySQL提供的FORUPDATE/LOCKINSHAREMODE特殊功能。详细的语法如下:SELECTSELECTselect_expr[FROMtable_references][WHERE[GROUPBYcol_name,…][HAVING[ORDER[ORDERBYcolname[ASC|DESC],[LIMITrow_count[OFFSEToffset]][FORUPDATE|LOCKINSHARE查询条NOTLIKE函数查与mysql相比,DBI函数的查询结果在数据精度上略有不同:无论字段为何种类型,COUNT的精度总JVM中的LONGMySQL中为BigInt,SUM和AVG的JVMBigDecimalMySQLBigDecimal对应的精度,所以DBISUMAVGMySQL返回的结果总是数值相等,精度不等。在对DBI函数结果进行字符串处理时需要注意这一点。DDBmysqlabs,length等,因为对标量函数,DBI无需多余的处理,只需要将函数直接下发给mysql获取结果集即可。分组与排序支持按复杂表达式进行分组和排序,但此时分组或排序表达式必须出现在支持对函数和标量函数进行排序,但对应的函数或表达式必须出现selectsum(score)fromscoregroupbyid;selectsum(score)fromscoregroupbyid;selectid,scorefromscoreorderbyscoredesc;--selectname,sum(score)fromusers,scorewhereusers.id=score.idandusers.id>0groupby;0orderbyscore--select100–scorefromscoreorderby100–score;selectid/2,sum(score)fromscoregroupbyid/2;-- selectid,max(score)fromscoregroupbyscoreorderbyselect*,max(score)fromscoregroupbyscoreorderby----按复杂表达式排序但该selectscorefromscoreorderby100–--参加排序 函数不在select列表selectidfromscoregroupbyscoreorderbyselect*fromscoregroupbyscoreorderby在构建分组和排序的SQL语句时,对出现在groupby和orderby后面的函数,标量函数以及表达式,必须同时出现在SELECT子句的列表中,否则会在生成执行计划时抛异常,做这样的限制是为了减少DBI驱动不必要的投影开销,使用时需要留意。多表联联接条件若包含多个子条件,则必须为AND关系,DDB不支持连接,必须包含至少接条件,join=--联接条件与外表条件间的顺序可以互80andusers.id=--联接外表没有指定选择select*fromusers,scorewhereusers.id=--多个联接条件==--联接条件为不等=Select*fromusers,score,classwhereuser.id=score.idscore.cid==--多表联接,虽然相邻的users和score表没有直接的join条件,但是可以根据score.id=class.id和user.id=class.id推导出user.id=score.id的joinSelect*fromusers,score,classwhereuser.id=class.idscore.id==----多个联接条件不能为orselect*fromusers,scorewhereusers.id>score.idor<=--联接条件包含算术表达式select*fromusers,scorewhereusers.id+1=score.id=--相邻的usersscore两表没有直接或间接的连接条Select*fromusers,score,classwhereuser.id===当distinct没有出现在函数中,那么distinct只能出现在select关键字后面,表示对整个select列表做distinct,返回记录列表中任意字段的值存在差异都将返回该distinct。distinct全字段的实现方法是将所的distinct没有意义,完全相同的两行会被groupby为一行。目前DBI不支持多个聚合函数中包含distinct。selectdistinctidfromselectdistinctidfromselectdistinctid,scorefromselectid,count(distinctscore)fromselectselectid,distinctscorefromselectid,count(distinctscore),sum(distinctscore)fromselectselect*fromscoreorderbyscoredesclimitselect*fromscoreorderbyscoredesclimit1offset1;select*fromscoreorderbyscoredesclimit1+1offset2*3;select*fromscoreorderbyscoredesclimit DDB支持MySQL特有的INDEX功能,如selectselect*from index(name)=--联接语句中也支 select*from index(name),=‘aaa’users.id=SQL_CACHESQL_CACHE和SQL_NO_CACHE关键字用于指定语句在执行之后,结果集是否在MySQL上缓存,对于一张表中的数据不经常被修改,而查询操作又非常频繁的情况下,MySQLquery_cache_type参数有关,具体SQLselectselect[distinct|SQL_CACHE|SQL_NO_CACHE]*|column1|column2...fromtable_name...高性SELECT间写出一些运行起来非常低效的SQL,这种现象尤其反映在SELECT语句中(因为DDBSELECT语句较为复杂SELECT语句的技巧,若开发者或DBA发现某个SELECT语句运行慢地不符合预期时,请参照本节内容。DDB4.5.7WHERE条件中包含均衡字段的判等条件SQL有很大可能落在一个数据节点上,而进入单节点查询优化路径的SQL因为DBISELECT1.5-5倍不等。SELECT,DDBselect出符合条件的所有数据,再一行策略user,A的均衡字段为a,B的均衡字段为b,构建SQL语句如:select*fromA,BwhereA.a=B.bandA.kkk= SQL,DDB会把连接下发给数据节点,直接获取最终结作为均衡字段的冗余表(保守估计差距在2-10倍。DDBSELECT语groupby包含均衡字段时,groupbygroupby的聚合函数都会直接下发给数据节点中做分组和聚合,而无需在DBI端再做Merge。groupby包含均衡字段可以极大节省DBI端开销,推荐应用开发者和DBA在为表选择给数据节点,无需DBI再做Merge,如表A均衡字段为a:selectcount(distincta)from limitnoffsetmlimitn+m下发给数据节点,再在中间大时会严重影响SQL执行效率,甚至导致OOM。DBI上做全局的堆排序,才能保障排序的正确性。这种情况下的堆排序开销较大。是否需要在聚合上排序取决于应用逻辑,应用开发者在SQL由于DDB一般包含多个数据节点,相比普通数据库而言,更容易出现过大结果集导致来避免OOM,使用方式如下:--PreparedStatement亦可,n>0,表示每DDB拉去的结果集大这个方法的调用需要在SQL之前DDB的流MySQL流方式关于DDB流方式的内容请参照DDB用户手册INSERTINSERT[IGNORE]INTOtablename[(colname,…)]VALUES(expr|DEFAULT|seq,…)[ONDUPLICATEKEYUPDATEcol_name=expr,…]否则该表无法保障数据在主键上全局唯一,进而无法保障ignore语义当SQL语句中包含ONDUPLICATEKEYUPDATE时,update的列不能是均衡字段。因为均衡字段的更新会带来数据迁移,会为DDB的运维带来风险一。当节点数量较多时,性能下降比较厉害,因此默认DDB不开启这个选项。在唯一性索引不是均衡字段的情况下,还有法保障字段全局唯一:为每个唯insert这张表的数据时,需要用一个分布式事务保证数据插入所有的冗余表中,例表A中有非均衡字段的唯一性索引字段a,b,c,为表A建冗余表A1,A2,A3,其中A1仅包含均衡字段a,A2仅包含均衡字段b,A3仅包含均衡字段c,在向表A中插入数据insertintoA(a,b,c)values(1,2,3);insertintoA1(a)values(1);insertintoA2(b)values(2);insertintoA3(c)全局自增IDisql@dba>>isql@dba>>showcreatetableinctest;CREATETABLE`inctest`(`id`bigint(20)NOT`uid`bigint(20)NOTNULLDEFAULT'0',KEY`uid`(`uid`))ENGINE=InnoDBDEFAULTCHARSET=utf8/*=user,ASSIGNIDTYPEIDMSB(Master统一批量分配)类型和TSB(基于时间戳的ID分配)类型,使用MSB的话,DBI每次分配ID功能不可用,TSBMSBTSB的内容请参照DDB用户手册。importimportConnectionconn=DriverManger.getConnection(url,user,pass);longid=((DBConnection)conn).allocateRecordId(<table>);ID则可能重复。获取到IDinsert指定自增长ID列插入到DDB中。JDBCID的方法:ConnectionConnectionconn=DriverManger.getConnection(url,user,pass);Statements=conn.createStatement();s.executeUpdate(“insertintotest(seq,--DDB4.5.7中seq可不写,不写则与使用标准JDBC完全一致。一些旧版本必须写seqResultSetrs=s.getGeneratedKeys();longid=强,三来也可以更好地控制DDB对用户代码的侵入。对应第法,可以使用selectallocate_record_idfromtable或selectallocate_record_idsfromtable语句作为SQLQSquery请求,前者只获取<1000allocate_record_ids直到获取到想要的数importimportConnectionconn=DriverManger.getConnection(url,user, allocate_record_idfromtable1”);longid=0;id=QSseq或不写,之后通过jdbcgetGenerateKeys()DBI的用法一致,需要特别注意的是,当插入批量数据时,getGenerateKeys()ID是定自增长字段为seq,否则会抛异常。批量插入数据节点进行归类,每个目标节点一条语句。因此,如果用户输入了以下SQL语句:“INSERT…VALUES DBN1DBN1:“INSERT…VALUESDBN2:“INSERT…VALUES同时,DDB设置defaultxa=0,则默认采用普通的一阶段事务进行插入操作,在这种场景下不能严XA事务相比的优势在于能够提供 DDB支持RECERECEINTOtable_name[(col_name,…)]DDB支持的RECEMySQL一致:当插入的数据与表已有数据在唯一索引或主键索引上有时,RECE会将已有行更新为RECE的数据行。另外对DDB而言,行的前提是行的均衡字段落在同一个DBN上。RECE操作依赖全局唯一性索引,与INSERTIGNORE一样,只有在表均衡字段是主键或主键中的一个字段时,DDB才能保障RECE的语义完整性。DDBRECEID分配和批量插入数据,在返回结果上,DDBRECE返回的修改行个数=更新行数*2+插入行个数。示例如下:isql@dba>>isql@dba>> ceintousertest23rowsmodified,executetime:138isql@dba>>showcreatetableinctest;CREATETABLE`inctest`(`id`bigint(20)NOT`uid`bigint(20)NOTNULLDEFAULT'0',KEY`uid`(`uid`))ENGINE=InnoDBDEFAULTCHARSET=utf8/*AUTO_INCREMENT_COLUMN=id,ASSIGNIDTYPE=MSB=user,isql@dba>> ceintoinctest(uid)4rowsmodified,executetime:209msGeneratedkeys | |13006|13007||13008|13009 UPDATEUPDATEtable_nameSETcol_name1=expr[col_name2=expr,…]WHEREwhere_condition[LIMITrow_count[OFFSEToffset]];DDB对UPDATE与insertonduplicatekeyupdate的限制相同,更新均衡字段会为DDB系统引入风UPDATE语句就可能造成数万行的数据迁移,而且还要在一无需更新并且具有较均匀的分布特性的字段作为均衡字段。如全局自增ID。不支持联表UPDATEDDB虽然支持联表查询,但不支持联表UPDATE。这个功能考虑在4.5.7以后的版本中支持。直观地说,DDB目前不支持UPDATE子句中包含多个表。DELETEFROMtable_nameWHEREwhere_condition[LIMITrow_count[OFFSETDELETEFROMtable_nameWHEREwhere_condition[LIMITrow_count[OFFSETDDB对DELETE过DDB使用CALL关键字来调用过程。语法如下callprocedure_name(param1, 按以上方法调用过程时,将在DDB的所有数据库节点上调用该过程。如果用户想只在某几个个别节点上执行,可以使用directforward来实现:/*/*FORWARDBY(TABLENAME=T1,T2;BFVALUE=1,2)*/call目前DDBJDBC逗号间隔,例如/*hint1,hint2*/select*fromtest_tbl。sqlmysql而获得正确的结果时,可以不经中间件处其中TABLENAME=TABLE1,TABLE2..是这条查询语句所涉及到的表,用来检查语句值,用于进行选择执行的DBN节点,BFVALUE参数是可选的。例如:T1.Score>90=T2.IDand(T1.ID=1orT1.ID=2)andT1.Score>在Isql中使用FORWARDBYhint中有分号,则需要通过DELIMITER命令修改/*FORWARDBY(TABLENAME=TABLE1,TABLE2,…;其中TABLE1.value1TABLE1的均衡字段;TABLE2.value1TABLE2的均衡使用FORWARDBY时,语句必须满足以下限制DirectforwardDDBDDB台节点上运行返回的结果是正确的,那就可以使用Directforward。(rplicainDDB负载均衡,提高分布式数据库实现负载均衡的SQL Slave上执行,TYPE=slaveprefer(Slave上执行,Slave其中,delay为可选项,表示用户指定的slave节点最大延时时间限制。若不指定延时时间,则只要slave节点有效(可连接并且正常)即可提供服务。四.附录DBIDDBJDBC驱动DBIJDBC3.0(JAVA)标准接口中的下列方法。调用未在下列给出的JDBC方法时将抛出异常。java.sql.DriverpublicConnectionconnect(Stringurl,Propertiesinfo)throwsSQLExceptionpublicBooleanacceptsURL(Stringurl)throwsSQLExceptionpublicintgetMajorVersion()publicintgetMinorVersion()publicboolean publicPreparedStatementprepareStatement(Stringsql)throwsSQLExceptionpublicvoid mit)throwsSQLExceptionpublicboolean mit()throwsSQLExceptionpublicvoidcommit()throwsSQLExceptionpublicvoidrollback()throwsSQLExceptionpublicvoidclose()throwsSQLExceptionpublicbooleanisClosed()throwsSQLExceptionpublicbooleanisReadOnly()throwsSQLExceptionpublicbooleansetReadOnly()throwsSQLExceptionpublicvoidclearWarnings()throwsSQLExceptionjava.sql.StatementpublicResultSetexecuteQuery(Stringsql)throwsSQLExceptionpublicintexecuteUpdate(Stringsql)throwsSQLExceptionpublicvoidclose()throwsSQLExceptionpublicbooleanexecute(Stringsql)throwsSQLExceptionpublicResultSetgetResultSet()throwsSQLExceptionpublicintgetUpdateCount()throwsSQLExceptionpublicConnectiongetConnection()throwsSQLExceptionpublicintgetFetchSize()throwsSQLExceptionpublicResultSetgetGeneratedKeys()throwsSQLExceptionpublicintgetMaxRows()throwsSQLExceptionpublicSQLWarninggetWarnings()throwsSQLExceptionpublicvoidclearWarnings()throwsSQLExceptionpublicbooleangetMoreResults()throwsSQLExceptionpublicintgetResultSetConcurrency()throwsSQLExceptionpublicintgetResultSetType()throwsSQLExceptionpublicbooleangetMoreResults(intcurrent)throwsSQLExceptionpublicintgetResultSetHoldability()throwsSQLExceptionpublicvoidsetFetchSize(introws)throwsSQLExceptionpublicvoidsetMaxRows(intmax)throwsjava.sql.PreparedStatementpublicResultSetexecuteQuery()throwsSQLExceptionpublicintexecuteUpdate()throwsSQLExceptionpublicbooleanexecute()throwsSQLExceptionpublicvoidsetBigDecimal(intparameterIndex,BigDecimalx)throwsSQLExceptionpublicvoidsetBinaryStream(intindex,InputStreamis,intsize)throwsSQLExceptionpublicvoidsetBlob(intparameterIndex,booleanx)throwsSQLExceptionpublicvoidsetBoolean(intparameterIndex,booleanx)throwsSQLExceptionpublicvoidsetByte(intparameterIndex,bytex)throwsSQLExceptionpublicvoidsetBytes(intparameterIndex,byte[]x)throwsSQLExceptionpublicvoidsetDate(intparameterIndex,Datex)throwsSQLExceptionpublicvoidsetDouble(intparameterIndex,doublex)throwsSQLExceptionpublicvoidsetFloat(intparameterIndex,floatx)throwsSQLExceptionpublicvoidsetInt(intparameterIndex,intx)throwsSQLExceptionpublicvoidsetLong(intparameterIndex,longx)throwsSQLExceptionpublicvoidsetShort(intparameterIndex,shortx)throwsSQLExceptionpublicvoidsetString(intparameterIndex,Stringx)throwsSQLExceptionpublicvoidsetTime(intparameterIndex,Timex)throwsSQLExceptionpublicvoidsetTimestamp(intparameterIndex,Timestampx)throwsSQLExceptionpublicvoidsetObject(intindex,Objectvalue)throwsSQLExceptionjava.sql.ResultSetpublicvoidclose()throwspublicBigDecimalgetBigDecimal(StringcolumnName)throwsSQLExceptionpublicInputStreamgetBinaryStream(intcolumn)throwsSQLExceptionpublicInputStreamgetBinaryStream(StringcolumnName)throwsSQLExceptionpublicBlobgetBlob(intcolumn)throwsSQLExceptionpublicBlobgetBlob(StringcolumnNames)throwsSQLExceptionpublicClobgetClob(intcolumn)throwsSQLExceptionpublicClobgetClob(StringcolumnNames)throwsSQLExceptionpublicbooleangetBoolean(intcolumn)throwsSQLExceptionpublicbooleangetBoolean(StringcolumnName)throwsSQLExceptionpublicbytegetByte(intcolumn)throwsSQLExceptionpublicbytegetByte(StringcolumnName)throwsSQLExceptionpublicbytegetBytes(intcolumn)throwsSQLExceptionpublicbytegetBytes(StringcolumnName)throwsSQLExceptionpublicDategetDate(intcolumn)throwsSQLExceptionpublicDategetDate(StringcolumnName)throwsSQLExceptionpublicdoublegetDouble(intcolumn)throwsSQLExceptionpublicdoublegetDouble(StringcolumnName)throwsSQLExceptionpublicfloatgetFloat(intcolumn)throwsSQLExceptionpublicfloatgetFloat(StringcolumnName)throwsSQLExceptionpublicintgetInt(intcolumn)throwsSQLExceptionpublicin
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- GB/T 17980.34-2026农药田间药效试验准则第34部分:杀菌剂防治马铃薯晚疫病
- 2026年答题模板公司生产安全培训内容
- 2026年防盗安全培训内容高分策略
- 2026年大学英语四级备考全攻略词汇语法听力写作全
- 向阳街道工作总结报告2026年快速入门
- 双鸭山市饶河县2025-2026学年第二学期六年级语文第五单元测试卷部编版含答案
- 2026年会务安全培训内容有哪些高分策略
- 铜仁地区玉屏侗族自治县2025-2026学年第二学期六年级语文第五单元测试卷部编版含答案
- 黔东南苗族侗族自治州凯里市2025-2026学年第二学期六年级语文第五单元测试卷部编版含答案
- 上饶市玉山县2025-2026学年第二学期六年级语文第五单元测试卷部编版含答案
- CJ/T 43-2005水处理用滤料
- T/CSWSL 012-2019淡水鱼用发酵饲料
- 机电安装专项方案
- 校长培训工作汇报
- 刑侦破案技巧与方法
- 2025年中国激光扫描共焦显微镜市场调查研究报告
- 2025年山东省济南市中考一模生物试题(一)(原卷版+解析版)
- 老年协会换届选举流程指南
- 科技进步奖申报培训
- 二零二五年度电梯井施工质量控制协议4篇
- 沥青路面施工方案
评论
0/150
提交评论