数据库-你可能忽略的东西

数据库的使用你可能忽略了这些

https://www.cnblogs.com/joylee/p/7768457.html

数据库的管理是一个很是专业的事情,对数据库的调优、监控通常是由数据库工程师完成,可是开发人员也常常与数据库打交道,即便是简单的增删改查也是有不少窍门,这里,一块儿来聊聊数据库中很容易忽略的问题。html

字段长度省着点用 先说说咱们经常使用的类型的存储长度:java

列类型 存储长度 tinyint 1字节 smallint 2字节 int 4字节 bigint 8字节 float 4字节 decimal(m,d) 0-4字节 datetime 8字节 timestamp 4字节 char(m) m个字节 varchar(m) 可变长度 text 可变长度 很明显,不一样的类型存储的长度有很大区别的,对查询的效率有影响,字段长度对索引的影响是很大的。node

字符串字段长度都差很少的,能够预估长度的,用char 字符串长度差别大,用varchar,限制长度,不要浪费空间 整型根据大小,选择合适的类型 时间建议用timestamp 建议使用decimal,不建议使用float,若是是价格,能够考虑用int或bigint,如1元,存储的就是100 放弃uuid(guid)的使用 无论是uuid,仍是guid,使用的时候都是为了不同时生成重复的ID,可是建议考虑其余方案,缘由以下:mysql

uuid没有顺序 uuid太长 uuid规则彻底不可控 推荐的方案用bigint(首选),或者char来存储,生成方式参考snowflake的算法,有顺序、长度固定、比uuid更短,固然,也几乎不会重复。linux

大表减小联表,最好是单表查询 单表查询的优点不少,查询效率极高,便于分表分库扩展,可是不少时候你们都以为真正实现起来不太现实,彻底失去了关系数据库的意义,可是单表的性能优点太明显,通常总会有办法解决的:程序员

合理的冗余字段 配合内存数据库(redis\mongodb)使用 联表变屡次查询(下文会有说明) 若是考虑都后期数据量大,须要分表分库,就应该尽早实时单表查询,如今的数据库分表分库的中间件基本都没法支持联表查询。即便如mycat最多支持两个表的联表查询,可是也有很明显的性能损耗。redis

索引的正确处理方式 索引的优点这里就很少说了,索引使用不当会有反效果:算法

数据量很小的表,不须要索引 一个表的索引不宜过多,建议最多就5个,索引不可能知足全部的场景,可是了个知足绝大部分的场景 mysql 和 sqlserver的索引差异还挺大的,须要注意。例如: mysql索引字段的顺序对性能有很大影响,sqlserver优化过,影响很小 多查几回比联表可能要好 提出这个方案相信会获得不少人的反对,可是我相信这个结论仍是很是适合数据量大的场景。多查几回数据库有这么几个弊端:sql

增长了网络消耗 增长了数据库的链接数 其实,这两个问题在如今基本均可以忽略的,数据库和应用的链接基本都是内网,这个网络链接的效率仍是很高的。数据库对链接池的优化已经比较成熟了,链接数只要不是太多,影响也不会太严重,可是多查几回的优点却不少:mongodb

单表效率更高 便于后期扩展分表分库库 有效利用数据库自己的结果缓存 减小锁表,联表会锁多个表 固然,多查几回这个度必定要把握。千万不要在一个循环里面查询数据库。咱们也应该尽可能减小查询数据库的次数。咱们能够接受1次查询变2次查询,若是你变成10次查询,那就要放弃了。 举个例子: 查询商品的时候,须要显示分类表的分类名

select category.name,product.name from product inner join category on p.categoryid=category.id 建议的方式:

select categoryid,name from product select categoryname from category where categoryid in ('','','','') 固然,你能够再优化一下,查询分类名以前,对product的categoryid排序一下,这样速度更快。由于咱们前面已经用snowflake生成了有顺序的主键了。 补充一下,in的效率并非你想象的那么慢,若是保持在100个节点(不少书籍介绍1000个节点,咱们保守一点),性能仍是很高的。

尽可能使用简单的数据库脚本 不少用过 .net Entity Framework 的人都说这个框架太慢,其实慢主要是两点:错误的使用延迟加载(外键关联)、生成SQL编译太慢。Entity Framework生成的SQL脚本有太多没用的东西,致使编译太慢。 数据库脚本尽可能使用简单的,不要用太长的一个SQL脚本,会致使初次执行的时候,编译SQL脚本花费太多的时间。

尽可能去避免聚合操做 聚合操做如count,group等,是数据库性能的大杀手,常常会出现大面积的表扫描和索表的状况,因此你们能看到不少平台都把数量的计算给隐藏了,商品查询不去实时显示count的结果。如淘宝,就不显示查询结果的数量,只是显示前100页。 避免聚合操做的方法就是将实时的count计算结果用字段去存储,去累加这个结果。固然,也能够考虑用spark等实时计算框架去处理,这种高深的技术,不在这次讨论范围内。(PS:主要是我也不懂)

总结 程序的优化不少时候都是一些细节的问题,更应该注意平时的积累,阿里SQL的规范有不少能够吸收的地方,以上也是本身工做中的一些总结,欢迎你们补充。

https://www.cnblogs.com/joylee/p/9521741.html

前言 以前写过一篇文章《数据库的使用你可能忽略了这些》,主要是从一些你们使用使用时容易忽略的地方,如:字段长度、表设计等来讲明,这篇文章一样也是这样的主题,只是从另外的几个方面来讲说数据库使用中,容易忽略,致使入坑的地方。

合理预估数据量 在数据库进行表设计的时候,就应该评估可能产生的数据量,数据量会对整个开发和代码的健壮性有很大的影响。开发一个数据量万级别、十万级别、百万级别、千万以上级别数量的应用,在开发思路、技术选型、架构都能都要很大的差异。 基本上的个人原则是:

万级别的数据库,能够随意一点,SQL编写有好的习惯; 十万级别,注意索引,注意联表性能; 百万级别,尽可能减小联表,尽可能不要作汇总查询,如查总数 ; 千万以上级别,除缓存以外,使用分表分库 ; 不少系统由于在设计表的时候,没有很好的预估的后期系统的发展,致使上线不久就出现没法支撑的状况,代码上太多的联表查询,不在意基础的SQL性能,致使数据库的瓶颈很快就显现出来,不得不重构系统。设计数据库的时候,必定是基于业务进行设计的,对业务的发展有必定的预估,看得长远一点。

合理预估并发访问量 数据库有自然的瓶颈,就是并发量。咱们通常会经过缓存来减小数据库的并发链接,以及对数据库的操做,数据库的并发,不是只有大型平台才会遇到,不少中小平台其实也会面临这样的问题,例如:

循环进行数据库的操做 这个问题,上一篇文章我也提到过,不要在循环里进行数据库的操做,这个会直接致使数据库链接数暴增,影响很是严重。虽然是个比较低级的问题,可是出现的几率实际上是很是高的,在我身边看到不少不少这种案例了,这种问题,就是须要程序员本身自己避免这些问题,固然,也能够经过一些手段去监控,找到这些问题,只是会比较麻烦一点。

业务自己的高频次数据请求 其实有些业务,即便是中小型的平台,也会有高并发请求数据库的状况,常见的例子如:日志。例如,咱们须要抓取到全部人的操做日志,或者全部模块的加载时间,而且持久化保存。若是,当初选型经过Mysql去记录这些数据,那么就很容易遇到高并发的问题。这种就是属于选型的错误了。

数据库对高并发的处理一直是短板,因此应该尽可能避免高并发的数据库操做,查询经过缓存处理,增删改这能够经过MQ或者Kafka这样的工具异步进行处理,若是对数据库的结构化要求不高,则能够用hbase或者hive进行数据库的保存。

数据库线程池的合理使用 如今数据库的操做都是使用线程池的,线程池主要是用来控制数据库的链接数,其实链接池是不属于数据库范畴,可是,通常咱们使用和数据库结合很是紧密,因此在这里一并说明。 通常线程池都会有这样的几个参数:

参数 说明 最小链接数 无论是否有数据库的操做,这几个链接都会一直存在, 最大链接数 容许的最大的链接数,若是超过了这个数据,则没法申请链接,只能等待,或者异常 回收时间 多长时间会对全部的链接进行一次断开,而后从新链接。 释放时间 多长时间没有进行操做的链接,会释放 基本全部的链接池都会有这几个参数,可能不一样的链接池参数名不一样,可是做用是同样的。 这里咱们重点说一下最大链接数,这个是很容易忽略的一个设置。 不少人设置最大链接数的时候,喜欢设置的很大,例如设置为5000,可是通常mysql的数据库一个实例链接默认才1000,链接数超过这个了数据库也没法处理,设置的再大实际上是没用的。

服务器数量 * 最大链接数 < 数据库最大链接数

并且,这仍是在一个实例,一个数据库的状况下,至于多个数据库: 我建议

服务器数量 * 最大链接数 * 数据库数量 < 数据库最大链接数

若是单个数据库占用了太多的数据库链接,会影响到其余数据库,致使其余数据库也没法使用。 固然,这个值你们能够根据业务去进行合理的估算,高频的业务分配多一点,低频的业务分配少一点。不要盲目的一味设置链接池的最大值。

总结 现在,虽然各类各样的存储方式出现,可是关系数据库一直是咱们系统的最重要的组成部分,尽可能不要过早暴露数据库应对并发的短板,设计数据库和操做数据库在咱们的开发中应该是一件很神圣的事情,认证对待关系的数据库的每个操做才是明智之举。

扩展阅读: 数据库的使用你可能忽略了这些 学会数据库读写分离、分表分库——用Mycat,这一篇就够了!

数据库读写分离、分表分库

https://www.cnblogs.com/joylee/p/7513038.html

系统开发中,数据库是很是重要的一个点。除了程序的自己的优化,如:SQL语句优化、代码优化,数据库的处理自己优化也是很是重要的。主从、热备、分表分库等都是系统发展早晚会遇到的技术问题问题。Mycat是一个广受好评的数据库中间件,已经在不少产品上进行使用了。但愿经过这篇文章的介绍,能学会Mycat的使用。 安装 Mycat官网:http://www.mycat.io/ 能够了解下Mycat的背景和应用状况,这样使用起来比较有信心。

Mycat下载地址:http://dl.mycat.io/ 官网有个文档,属于详细的介绍,初次入门,看起来比较花时间。

下载: 建议你们选择 1.6-RELEASE 版本,毕竟是比较稳定的版本。

安装: 根据不一样的系统选择不一样的版本。包括linux、windows、mac,做者考虑仍是很是周全的,固然,也有源码版的。(ps:源码版的下载后,只要配置正确,就能够正常运行调试,这个赞一下。)

Mycat的安装其实只要解压下载的目录就能够了,很是简单。 安装完成后,目录以下:

目录 说明 bin mycat命令,启动、重启、中止等 catlet catlet为Mycat的一个扩展功能 conf Mycat 配置信息,重点关注 lib Mycat引用的jar包,Mycat是java开发的 logs 日志文件,包括Mycat启动的日志和运行的日志。 配置 Mycat的配置文件都在conf目录里面,这里介绍几个经常使用的文件:

文件 说明 server.xml Mycat的配置文件,设置帐号、参数等 schema.xml Mycat对应的物理数据库和数据库表的配置 rule.xml Mycat分片(分库分表)规则 Mycat的架构其实很好理解,Mycat是代理,Mycat后面就是物理数据库。和Web服务器的Nginx相似。对于使用者来讲,访问的都是Mycat,不会接触到后端的数据库。 咱们如今作一个主从、读写分离,简单分表的示例。结构以下图:

服务器 IP 说明 Mycat 192.168.0.2 mycat服务器,链接数据库时,链接此服务器 database1 192.168.0.3 物理数据库1,真正存储数据的数据库 database2 192.168.0.4 物理数据库2,真正存储数据的数据库 Mycat做为主数据库中间件,确定是与代码弱关联的,因此代码是不用修改的,使用Mycat后,链接数据库是不变的,默认端口是8066。链接方式和普通数据库同样,如:jdbc:mysql://192.168.0.2:8066/

server.xml

示例

<user name="test"> <property name="password">test</property> <property name="schemas">lunch</property> <property name="readOnly">false</property>

<!-- 表级 DML 权限设置 -->
    <!--        
    <privileges check="false">
        <schema name="TESTDB" dml="0110" >
            <table name="tb01" dml="0000"></table>
            <table name="tb02" dml="1111"></table>
        </schema>
    </privileges>       
     -->
</user>

重点关注下面这段,其余默认便可。

参数 说明 user 用户配置节点 --name 登陆的用户名,也就是链接Mycat的用户名 --password 登陆的密码,也就是链接Mycat的密码 --schemas 数据库名,这里会和schema.xml中的配置关联,多个用逗号分开,例如须要这个用户须要管理两个数据库db1,db2,则配置db1,dbs --privileges 配置用户针对表的增删改查的权限,具体见文档吧 我这里配置了一个帐号test 密码也是test,针对数据库lunch,读写权限都有,没有针对表作任何特殊的权限。

schema.xml schema.xml是最主要的配置项,首先看个人配置文件。

<?xml version="1.0"?>

<!DOCTYPE mycat:schema SYSTEM "schema.dtd">

<mycat:schema xmlns:mycat="http://io.mycat/">

<!-- 数据库配置,与server.xml中的数据库对应 -->

<schema name="lunch" checkSQLschema="false" sqlMaxLimit="100">
    <table name="lunchmenu" dataNode="dn1"  />
    <table name="restaurant" dataNode="dn1"  />
    <table name="userlunch" dataNode="dn1"  />
    <table name="users" dataNode="dn1"  />
    <table name="dictionary" primaryKey="id" autoIncrement="true" dataNode="dn1,dn2"  rule="mod-long" />

    
</schema>

<!-- 分片配置 -->

<dataNode name="dn1" dataHost="test1" database="lunch" />
<dataNode name="dn2" dataHost="test2" database="lunch" />

<!-- 物理数据库配置 -->

<dataHost name="test1" maxCon="1000" minCon="10" balance="0"  writeType="0" dbType="mysql" dbDriver="native">
    <heartbeat>select user();</heartbeat>
    <writeHost host="hostM1" url="192.168.0.2:3306" user="root" password="123456">  
    </writeHost>
</dataHost>

<dataHost name="test2" maxCon="1000" minCon="10" balance="0" writeType="0" dbType="mysql" dbDriver="native">
    <heartbeat>select user();</heartbeat>
    <writeHost host="hostS1" url="192.168.0.3:3306" user="root" password="123456">  
    </writeHost>
</dataHost>

</mycat:schema> 参数 说明 schema 数据库设置,此数据库为逻辑数据库,name与server.xml中schema对应 dataNode 分片信息,也就是分库相关配置 dataHost 物理数据库,真正存储数据的数据库 每一个节点的属性逐一说明:

schema:

属性 说明 name 逻辑数据库名,与server.xml中的schema对应 checkSQLschema 数据库前缀相关设置,建议看文档,这里暂时设为folse sqlMaxLimit select 时默认的limit,避免查询全表 table:

属性 说明 name 表名,物理数据库中表名 dataNode 表存储到哪些节点,多个节点用逗号分隔。节点为下文dataNode设置的name primaryKey 主键字段名,自动生成主键时须要设置 autoIncrement 是否自增 rule 分片规则名,具体规则下文rule详细介绍 dataNode

属性 说明 name 节点名,与table中dataNode对应 datahost 物理数据库名,与datahost中name对应 database 物理数据库中数据库名 dataHost

属性 说明 name 物理数据库名,与dataNode中dataHost对应 balance 均衡负载的方式 writeType 写入方式 dbType 数据库类型 heartbeat 心跳检测语句,注意语句结尾的分号要加。 应用场景 数据库分表分库 配置以下:

<?xml version="1.0"?>

<!DOCTYPE mycat:schema SYSTEM "schema.dtd">

<mycat:schema xmlns:mycat="http://io.mycat/">

<!-- 数据库配置,与server.xml中的数据库对应 -->

<schema name="lunch" checkSQLschema="false" sqlMaxLimit="100">
    <table name="lunchmenu" dataNode="dn1"  />
    <table name="restaurant" dataNode="dn1"  />
    <table name="userlunch" dataNode="dn1"  />
    <table name="users" dataNode="dn1"  />
    <table name="dictionary" primaryKey="id" autoIncrement="true" dataNode="dn1,dn2"  rule="mod-long" />

    
</schema>

<!-- 分片配置 -->

<dataNode name="dn1" dataHost="test1" database="lunch" />
<dataNode name="dn2" dataHost="test2" database="lunch" />

<!-- 物理数据库配置 -->

<dataHost name="test1" maxCon="1000" minCon="10" balance="0"  writeType="0" dbType="mysql" dbDriver="native">
    <heartbeat>select user();</heartbeat>
    <writeHost host="hostM1" url="192.168.0.2:3306" user="root" password="123456">  
    </writeHost>
</dataHost>

<dataHost name="test2" maxCon="1000" minCon="10" balance="0" writeType="0" dbType="mysql" dbDriver="native">
    <heartbeat>select user();</heartbeat>
    <writeHost host="hostS1" url="192.168.0.3:3306" user="root" password="123456">  
    </writeHost>
</dataHost>

</mycat:schema> 我在192.168.0.二、192.168.0.3均有数据库lunch。 lunchmenu、restaurant、userlunch、users这些表都只写入节点dn1,也就是192.168.0.2这个服务,而dictionary写入了dn一、dn2两个节点,也就是192.168.0.二、192.168.0.3这两台服务器。分片的规则为:mod-long。 主要关注rule属性,rule属性的内容来源于rule.xml这个文件,Mycat支持10种分表分库的规则,基本能知足你所须要的要求,这个必须赞一个,其余数据库中间件好像都没有这么多。 table中的rule属性对应的就是rule.xml文件中tableRule的name,具体有哪些分表和分库的实现,建议仍是看下文档。我这里选择的mod-long就是将数据平均拆分。由于我后端是两台物理库,因此rule.xml中mod-long对应的function count为2,见下面部分代码:

<tableRule name="mod-long"> <rule> <columns>id</columns> <algorithm>mod-long</algorithm> </rule> </tableRule>

<function name="mod-long" class="io.mycat.route.function.PartitionByMod"> <!-- how many data nodes --> <property name="count">2</property> </function> 数据库读写分离 配置以下:

<?xml version="1.0"?>

<!DOCTYPE mycat:schema SYSTEM "schema.dtd">

<mycat:schema xmlns:mycat="http://io.mycat/">

<!-- 数据库配置,与server.xml中的数据库对应 -->

<schema name="lunch" checkSQLschema="false" sqlMaxLimit="100">
    <table name="lunchmenu" dataNode="dn1"  />
    <table name="restaurant" dataNode="dn1"  />
    <table name="userlunch" dataNode="dn1"  />
    <table name="users" dataNode="dn1"  />
    <table name="dictionary" primaryKey="id" autoIncrement="true" dataNode="dn1"  />

    
</schema>

<!-- 分片配置 -->

<dataNode name="dn1" dataHost="test1" database="lunch" />

<!-- 物理数据库配置 -->

<dataHost name="test1" maxCon="1000" minCon="10" balance="1"  writeType="0" dbType="mysql" dbDriver="native">
    <heartbeat>select user();</heartbeat>
    <writeHost host="hostM1" url="192.168.0.2:3306" user="root" password="123456">  
    <readHost host="hostM1" url="192.168.0.3:3306" user="root" password="123456">   
    </readHost>
    </writeHost>
</dataHost>

</mycat:schema> 这样的配置与前一个示例配置改动以下: 删除了table分配的规则,以及datanode只有一个 datahost也只有一台,可是writehost总添加了readhost,balance改成1,表示读写分离。 以上配置达到的效果就是102.168.0.2为主库,192.168.0.3为从库。

注意:Mycat主从分离只是在读的时候作了处理,写入数据的时候,只会写入到writehost,须要经过mycat的主从复制将数据复制到readhost,这个问题当时候我纠结了很久,数据写入writehost后,readhost一直没有数据,觉得是本身配置的问题,后面才发现Mycat就没有实现主从复制的功能,毕竟数据库自己自带的这个功能才是最高效稳定的。

至于其余的场景,如同时主从和分表分库也是支持的了,只要了解这个实现之后再去修改配置,都是能够实现的。而热备及故障专业官方推荐使用haproxy配合一块儿使用,你们能够试试。

使用 Mycat的启动也很简单,启动命令在Bin目录:

##启动 mycat start

##中止 mycat stop

##重启 mycat restart 若是在启动时发现异常,在logs目录中查看日志。

wrapper.log 为程序启动的日志,启动时的问题看这个 mycat.log 为脚本执行时的日志,SQL脚本执行报错后的具体错误内容,查看这个文件。mycat.log是最新的错误日志,历史日志会根据时间生成目录保存。 mycat启动后,执行命令不成功,可能实际上配置有错误,致使后面的命令没有很好的执行。

Mycat带来的最大好处就是使用是彻底不用修改原有代码的,在mycat经过命令启动后,你只须要将数据库链接切换到Mycat的地址就能够了。以下面就能够进行链接了:

mysql -h192.168.0.1 -P8806 -uroot -p123456 链接成功后能够执行sql脚本了。 因此,能够直接经过sql管理工具(如:navicat、datagrip)链接,执行脚本。我一直用datagrip来进行平常简单的管理,这个很方便。

Mycat还有一个管理的链接,端口号是9906.

mysql -h192.168.0.1 -P9906 -uroot -p123456 链接后能够根据管理命令查看Mycat的运行状况,固然,喜欢UI管理方式的人,能够安装一个Mycat-Web来进行管理,有兴趣自行搜索。

简而言之,开发中使用Mycat和直接使用Mysql机会没有差异。

常见问题 使用Mycat后总会遇到一些坑,我将本身遇到的一些问题在这里列一下,但愿能与你们有共鸣:

Mycat是否是配置之后,就能彻底解决分表分库和读写分离问题? Mycat配合数据库自己的复制功能,能够解决读写分离的问题,可是针对分表分库的问题,不是完美的解决。或者说,至今为止,业界没有完美的解决方案。 分表分库写入能完美解决,可是,不能完美解决主要是联表查询的问题,Mycat支持两个表联表的查询,多余两个表的查询不支持。 其实,不少数据库中间件关于分表分库后查询的问题,都是须要本身实现的,并且节本都不支持联表查询,Mycat已经算作地很是先进了。 分表分库的后联表查询问题,你们经过合理数据库设计来避免。

Mycat支持哪些数据库,其余平台如 .net、PHP能用吗? 官方说了,支持的数据库包括MySQL、SQL Server、Oracle、DB二、PostgreSQL 等主流数据库,很赞。 尽可能用Mysql,我试过SQL Server,会有些小问题,由于部分语法有点差别。

Mycat 非JAVA平台如 .net、PHP能用吗? 能够用。这一点MyCat作的也很棒。

参考 《Mycat权威指南》: http://www.mycat.io/document/Mycat_V1.6.0.pdf 官网 :http://www.mycat.io/

相关文章
相关标签/搜索