关于SQL 与 NoSQL的区别

转载自:http://blog.csdn.net/xlgen157387/article/details/47908797

云计算背后的秘密:NoSQL诞生的原因和优缺点

我本来一直觉得NoSQL其实很容易理解的,我本身也已经对NoSQL有了非常深入的研究,但是在最近准备YunTable的Chart的时候,发现NoSQL不仅非常博大精深,而且我个人对NoSQL的理解也只是皮毛而已,但我还算是一个“知耻而后勇”的人,所以经过一段时间的学习之后,从本系列第六篇开始,就将和大家聊聊NoSQL,而本篇将主要给大家做一下NoSQL数据库的综述。 
首先将和大家聊聊为什么NoSQL会在关系型数据库已经非常普及的情况下异军突起?

诞生的原因

随着互联网的不断发展,各种类型的应用层出不穷,所以导致在这个云计算的时代,对技术提出了更多的需求,主要体现在下面这四个方面: 
1. 低延迟的读写速度:应用快速地反应能极大地提升用户的满意度; 
2. 支撑海量的数据和流量:对于搜索这样大型应用而言,需要利用PB级别的数据和能应对百万级的流量; 
3. 大规模集群的管理:系统管理员希望分布式应用能更简单的部署和管理;

  1. 庞大运营成本的考量:IT经理们希望在硬件成本、软件成本和人力成本能够有大幅度地降低;

目前世界上主流的存储系统大部分还是采用了关系型数据库,其主要有一下优点:

1.事务处理—保持数据的一致性;

2.由于以标准化为前提,数据更新的开销很小(相同的字段基本上只有一处);

3.可以进行Join等复杂查询。

虽然关系型数据库已经在业界的数据存储方面占据不可动摇的地位,但是由于其天生的几个限制,使其很难满足上面这几个需求: 
1. 扩展困难:由于存在类似Join这样多表查询机制,使得数据库在扩展方面很艰难;
2. 读写慢:这种情况主要发生在数据量达到一定规模时由于关系型数据库的系统逻辑非常复杂,使得其非常容易发生死锁等的并发问题,所以导致其读写速度下滑非常严重;
3. 成本高:企业级数据库的License价格很惊人,并且随着系统的规模,而不断上升;
4. 有限的支撑容量:现有关系型解决方案还无法支撑Google这样海量的数据存储;
业界为了解决上面提到的几个需求,推出了多款新类型的数据库,并且由于它们在设计上和传统的NoSQL数据库相比有很大的不同,所以被统称为“NoSQL”系列数据库。总的来说,在设计上,它们非常关注对数据高并发地读写和对海量数据的存储等,与关系型数据库相比,它们在架构和数据模型方量面做了“减法”,而在扩展和并发等方面做了“加法”。现在主流的NoSQL数据库有BigTable、Hbase、Cassandra、SimpleDB、CouchDB、MongoDBRedis等。接下来,将关注NoSQL数据库到底存在哪些优缺点。

优缺点

在优势方面,主要体现在下面这三点: 
1. 简单的扩展:典型例子是Cassandra,由于其架构是类似于经典的P2P,所以能通过轻松地添加新的节点来扩展这个集群; 
2. 快速的读写:主要例子有redis,由于其逻辑简单,而且纯内存操作,使得其性能非常出色,单节点每秒可以处理超过10万次读写操作; 
3. 低廉的成本:这是大多数分布式数据库共有的特点,因为主要都是开源软件,没有昂贵的License成本; 
4. 
但瑕不掩瑜,NoSQL数据库还存在着很多的不足,常见主要有下面这几个: 
1. 不提供对SQL的支持:如果不支持SQL这样的工业标准,将会对用户产生一定的学习和应用迁移成本; 
2. 支持的特性不够丰富:现有产品所提供的功能都比较有限,大多数NoSQL数据库都不支持事务,也不像MS SQL Server和Oracle那样能提供各种附加功能,比如BI和报表等; 
3. 现有产品的不够成熟:大多数产品都还处于初创期,和关系型数据库几十年的完善不可同日而语; 
上面NoSQL产品的优缺点都是些比较共通的,在实际情况下,每个产品都会根据自己所遵从的数据模型和CAP理念而有所不同,接下来,将给大家介绍NoSQL两个最重要的概念:数据模型和CAP理念,并在本文最后,对主流的NoSQL数据库进行分类。

Naresh Kumar是位软件工程师与热情的博主,对于编程与新事物拥有极大的兴趣,非常乐于与其他开发者和程序员分享技术上的研究成果。近日,Naresh撰文比较了NoSQL与RDBMS,并详细介绍了他们各自的特点与适用的场景。

NoSQL并不是关系型数据库管理系统,本文将会介绍NoSQL数据库与关系型数据库之间的差别,同时还会讨论在何种场景下应该使用NoSQL,何种场景下不应该使用。由于NoSQL还是个相对较新的技术,因此它还面临着很多挑战。

时至今日,互联网上有数以亿计的用户。大数据与云计算已经成为很多主要的互联网应用都在使用或是准备使用的技术,这是因为互联网用户每天都在不断增长,数据也变得越来越复杂,而且有很多非结构化的数据存在,这是很难通过传统的关系型数据库管理系统来处理的。NoSQL技术则能比较好地解决这个问题,它主要用于非结构化的大数据与云计算上。从这个角度来看,NoSQL是一种全新的数据库思维方式。

为何要使用NoSQL数据库?

1.NoSQL具有灵活的数据模型,可以处理非结构化/半结构化的大数据

现在,我们可以通过Facebook、D&B等第三方轻松获得与访问数据,如个人用户信息、地理位置数据、社交图谱、用户产生的内容、机器日志数据以及传感器生成的数据等。对这些数据的使用正在快速改变着通信、购物、广告、娱乐以及关系管理的特质。没有使用这些数据的应用很快就会被用户所遗忘。开发者希望使用非常灵活的数据库,能够轻松容纳新的数据类型,并且不会被第三方数据提供商内容结构的变化所累。很多新数据都是非结构化或是半结构化的,因此开发者还需要能够高效存储这种数据的数据库。但遗憾的是,关系型数据库所使用的定义严格、基于模式的方式是无法快速容纳新的数据类型的,对于非结构化或是半结构化的数据更是无能为力。NoSQL提供的数据模型则能很好地满足这种需求。很多应用都会从这种非结构化数据模型中获益,比如说CRM、ERP、BPM等等,他们可以通过这种灵活性存储数据而无需修改表或是创建更多的列。这些数据库也非常适合于创建原型或是快速应用,因为这种灵活性使得新特性的开发变得非常容易。

2.NoSQL很容易实现可伸缩性(向上扩展与水平扩展)

如果有很多用户在频繁且并发地使用你的应用,那么你就需要考虑可伸缩的数据库技术而非传统的RDBMS了。对于关系型技术来说,很多应用开发者会发现动态的可伸缩性是难以实现的,这时就应该考虑切换到NoSQL数据库上。对于云应用来说,关系型数据库一开始是普遍的选择。然而,在使用过程中却遇到了越来越多的问题,原因就在于他们是中心化的,向上扩展而非水平扩展的。这使得他们不适合于那些需要简单且动态可伸缩性的应用。NoSQL数据库从一开始就是分布式、水平扩展的,因此非常适合于互联网应用分布式的特性。

在三层互联网架构的Web/应用层上,多年来向上扩展已经成为默认的扩展方式了。随着应用使用人数的激增,我们需要添加更多的服务器,性能则是通过负载均衡来实现的,这时的代价与用户数量成线性比例关系。在NoSQL数据库之前,数据库层的默认扩展方式就是向上扩展。为了支持更多的并发用户以及存储更多的数据,你需要越来越好的服务器,更好的CPU、更多的内存、更大的磁盘来维护所有表。然而,好的服务器意味着更加复杂、私有、并且也更加昂贵。这与Web/应用层所使用的便宜的硬件形成了鲜明的对比。

3.动态模式

关系型数据库需要在添加数据前先定义好模式。比如说,你需要存储客户的电话号码、姓名、地址、城市与州等信息,SQL数据库需要提前知晓你要存的是什么。这对于敏捷开发模式来说是场灾难,因为每次完成新特性时,数据库的模式通常都需要改变。因此,如果在开发过程中想将客户喜欢的条目加到数据库中,那就得向表中添加这一列才行,然后要做的就是将整个数据库迁移到新的模式上。

4.自动分片

由于是结构化的,关系型数据库通常会垂直扩展,单台服务器要持有整个数据库来确保可靠性与数据的持续可用性。这样做的代价就是非常昂贵、扩展受到限制,并且数据库基础设施会成为失败点。这个问题的解决方案就是水平扩展,添加服务器而不是为单台服务器增加更多的能力。NoSQL数据库通常都支持自动分片,这意味着他们本质上就会自动在多台服务器上分发数据,应用甚至都不知道这些事情。数据与查询负载会自动在多台服务器上做到平衡,当某台服务器当机时,它能快速且透明地被替换掉。

5.复制

大多数NoSQL数据库也支持自动复制,这意味着你可以获得高可用性与灾备恢复功能。从开发者的角度来看,存储环境本质上是虚拟化的。

NoSQL数据库面临的挑战

1.成熟度

RDBMS系统由来已久。NoSQL拥护者们会说RDBMS的高龄是其衰退的标志,不过对于大多数CIO来说,RDBMS的成熟让人放心。对于大多数情况来说,RDBMS系统是稳定且功能丰富的。相比较而言,大多数NoSQL数据库则还有很多特性有待实现。

2.支持

企业需要的是安心,如果关键系统出现了故障,他们可以获得即时的支持。所有RDBMS厂商都在不遗余力地提供良好的企业支持。与之相反,大多数NoSQL系统都是开源项目,虽然每种数据库都有那么几家公司提供支持,不过这些公司大多都是小的初创公司,没有全球支持资源,也没有oracle、微软或是IBM那种令人放心的公信力。

3.分析与商业智能

NoSQL数据库在Web 2.0应用时代开始出现。因此,大多数特性都是面向这些应用的需要的。然而,应用中的数据对于业务来说是有价值的,这种价值远远超出了Web应用那种CRUD。企业数据库中的业务信息可以帮助改进效率并提升竞争力,商业智能对于大中型企业来说是个非常关键的IT问题。

4.管理

NoSQL的设计目标是提供零管理的解决方案,不过当今的现实却离这个目标还相去甚远。现在的NoSQL需要很多技巧才能用好,并且需要不少人力、物力来维护。

5.专业

全球有很多开发者,每个业务部门都会有熟悉RDBMS概念与编程的人。相反,几乎每个NoSQL开发者都处于学习模式。这种状况会随着时间的流逝而发生改观。但现在,找到一个有经验的RDBMS程序员或是管理员要比NoSQL专家容易多了。

结论

NoSQL数据库正在成为数据库领域的重要力量。如果使用恰当,那么它会带来很多好处。然而,企业应该非常小心并注意到这些数据库的限制与问题。

NoSQL这两年越来越热,尤其是大型互联网公司非常热衷这门技术。根据笔者的经验,并不是任何场景,NoSQL都要优于关系型数据库。下面我们来具体聊聊,什么时候使用NoSQL比较给力:

1) 数据库表schema经常变化 
比如在线商城,维护产品的属性经常要增加字段,这就意味着ORMapping层的代码和配置要改,如果该表的数据量过百万,新增字段会带来额外开销(重建索引等)。NoSQL应用在这种场景,可以极大提升DB的可伸缩性,开发人员可以将更多的精力放在业务层。

2)数据库表字段是复杂数据类型

对于复杂数据类型,比如SQL Sever提供了可扩展性的支持,像xml类型的字段。很多用过的同学应该知道,该字段不管是查询还是更改,效率非常一般。主要原因是是DB层对xml字段很难建高效索引,应用层又要做从字符流到dom的解析转换。NoSQL以json方式存储,提供了原生态的支持,在效率方便远远高于传统关系型数据库。

3)高并发数据库请求

此类应用常见于web2.0的网站,很多应用对于数据一致性要求很低,而关系型数据库的事务以及大表join反而成了”性能杀手”。在高并发情况下,sql与no-sql的性能对比由于环境和角度不同一直是存在争议的,并不是说在任何场景,no-sql总是会比sql快。有篇article和大家分享下,http://artur.ejsmont.org/blog/content/insert-performance-comparison-of-nosql-vs-sql-servers

4)海量数据的分布式存储

海量数据的存储如果选用大型商用数据,如Oracle,那么整个解决方案的成本是非常高的,要花很多钱在软硬件上。NoSQL分布式存储,可以部署在廉价的硬件上,是一个性价比非常高的解决方案。Mongo的auto-sharding已经运用到了生产环境。http://www.mongodb.org/display/DOCS/Sharding

并不是说NoSQL可以解决一切问题,像ERP系统、BI系统,在大部分情况还是推荐使用传统关系型数据库。主要的原因是此类系统的业务模型复杂,使用NoSQL将导致系统的维护成本增加。

为什么要使用NoSQL

NoSQL概念 
随着web2.0的快速发展,非关系型、分布式数据存储得到了快速的发展,它们不保证关系数据的ACID特性。NoSQL概念在2009年被提了出来。NoSQL最常见的解释是“non-relational”,“Not Only SQL”也被很多人接受。(“NoSQL”一词最早于1998年被用于一个轻量级的关系数据库的名字。)

NoSQL被我们用得最多的当数key-value存储,当然还有其他的文档型的、列存储、图型数据库、xml数据库等。在NoSQL概念提出之前,这些数据库就被用于各种系统当中,但是却很少用于web互联网应用。比如cdb、qdbm、bdb数据库。

传统关系数据库的瓶颈 
传统的关系数据库具有不错的性能,高稳定型,久经历史考验,而且使用简单,功能强大,同时也积累了大量的成功案例。在互联网领域,MySQL成为了绝对靠前的王者,毫不夸张的说,mysql为互联网的发展做出了卓越的贡献。

在90年代,一个网站的访问量一般都不大,用单个数据库完全可以轻松应付。在那个时候,更多的都是静态网页,动态交互类型的网站不多。

到了最近10年,网站开始快速发展。火爆的论坛、博客、sns、微博逐渐引领web领域的潮流。在初期,论坛的流量其实也不大,如果你接触网络比较早,你可能还记得那个时候还有文本型存储的论坛程序,可以想象一般的论坛的流量有多大。

Memcached+MySQL 
后来,随着访问量的上升,几乎大部分使用MySQL架构的网站在数据库上都开始出现了性能问题,web程序不再仅仅专注在功能上,同时也在追求性能。程序员们开始大量的使用缓存技术来缓解数据库的压力,优化数据库的结构和索引。开始比较流行的是通过文件缓存来缓解数据库压力,但是当访问量继续增大的时候,多台web机器通过文件缓存不能共享,大量的小文件缓存也带了了比较高的IO压力。在这个时候,Memcached就自然的成为一个非常时尚的技术产品。

Memcached作为一个独立的分布式的缓存服务器,为多个web服务器提供了一个共享的高性能缓存服务,在Memcached服务器上,又发展了根据hash算法来进行多台Memcached缓存服务的扩展,然后又出现了一致性hash来解决增加或减少缓存服务器导致重新hash带来的大量缓存失效的弊端。当时,如果你去面试,你说你有Memcached经验,肯定会加分的。

Mysql主从读写分离 
由于数据库的写入压力增加,Memcached只能缓解数据库的读取压力。读写集中在一个数据库上让数据库不堪重负,大部分网站开始使用主从复制技术来达到读写分离,以提高读写性能和读库的可扩展性。Mysql的master-slave模式成为这个时候的网站标配了。

分表分库 
随着web2.0的继续高速发展,在Memcached的高速缓存,MySQL的主从复制,读写分离的基础之上,这时MySQL主库的写压力开始出现瓶颈,而数据量的持续猛增,由于MyISAM使用表锁,在高并发下会出现严重的锁问题,大量的高并发MySQL应用开始使用InnoDB引擎代替MyISAM。同时,开始流行使用分表分库来缓解写压力和数据增长的扩展问题。这个时候,分表分库成了一个热门技术,是面试的热门问题也是业界讨论的热门技术问题。也就在这个时候,MySQL推出了还不太稳定的表分区,这也给技术实力一般的公司带来了希望。虽然MySQL推出了MySQL Cluster集群,但是由于在互联网几乎没有成功案例,性能也不能满足互联网的要求,只是在高可靠性上提供了非常大的保证。

MySQL的扩展性瓶颈 
在互联网,大部分的MySQL都应该是IO密集型的,事实上,如果你的MySQL是个CPU密集型的话,那么很可能你的MySQL设计得有性能问题,需要优化了。大数据量高并发环境下的MySQL应用开发越来越复杂,也越来越具有技术挑战性。分表分库的规则把握都是需要经验的。虽然有像淘宝这样技术实力强大的公司开发了透明的中间件层来屏蔽开发者的复杂性,但是避免不了整个架构的复杂性。分库分表的子库到一定阶段又面临扩展问题。还有就是需求的变更,可能又需要一种新的分库方式。

MySQL数据库也经常存储一些大文本字段,导致数据库表非常的大,在做数据库恢复的时候就导致非常的慢,不容易快速恢复数据库。比如1000万4KB大小的文本就接近40GB的大小,如果能把这些数据从MySQL省去,MySQL将变得非常的小。

关系数据库很强大,但是它并不能很好的应付所有的应用场景。MySQL的扩展性差(需要复杂的技术来实现),大数据下IO压力大,表结构更改困难,正是当前使用MySQL的开发人员面临的问题。

NOSQL的优势

易扩展 
NoSQL数据库种类繁多,但是一个共同的特点都是去掉关系数据库的关系型特性。数据之间无关系,这样就非常容易扩展。也无形之间,在架构的层面上带来了可扩展的能力。

大数据量,高性能 
NoSQL数据库都具有非常高的读写性能,尤其在大数据量下,同样表现优秀。这得益于它的无关系性,数据库的结构简单。一般MySQL使用Query Cache,每次表的更新Cache就失效,是一种大粒度的Cache,在针对web2.0的交互频繁的应用,Cache性能不高。而NoSQL的Cache是记录级的,是一种细粒度的Cache,所以NoSQL在这个层面上来说就要性能高很多了。

灵活的数据模型 
NoSQL无需事先为要存储的数据建立字段,随时可以存储自定义的数据格式。而在关系数据库里,增删字段是一件非常麻烦的事情。如果是非常大数据量的表,增加字段简直就是一个噩梦。这点在大数据量的web2.0时代尤其明显。

高可用 
NoSQL在不太影响性能的情况,就可以方便的实现高可用的架构。比如Cassandra,hbase模型,通过复制模型也能实现高可用。

总结 
NoSQL数据库的出现,弥补了关系数据(比如MySQL)在某些方面的不足,在某些方面能极大的节省开发成本和维护成本。 
MySQL和NoSQL都有各自的特点和使用的应用场景,两者的紧密结合将会给web2.0的数据库发展带来新的思路。让关系数据库关注在关系上,NoSQL关注在存储上。

关系数据库还是NoSQL数据库

上一篇简单的说明了为什么要使用NoSQL。接下来我们看下如何把NoSQL引入到我们的项目中,我们到底要不要把NoSQL引入到项目中。

在过去,我们只需要学习和使用一种数据库技术,就能做几乎所有的数据库应用开发。因为成熟稳定的关系数据库产品并不是很多,而供你选择的免费版本就更加少了,所以互联网领域基本上都选择了免费的MySQL数据库。在高速发展的WEB2.0时代,我们发现关系数据库在性能、扩展性、数据的快速备份和恢复、满足需求的易用性上并不总是能很好的满足我们的需要,我们越来越趋向于根据业务场景选择合适的数据库,以及进行多种数据库的融合运用。几年前的一篇文章《One Size Fits All - An Idea Whose Time Has Come and Gone》就已经阐述了这个观点。

当我们在讨论是否要使用NoSQL的时候,你还需要理解NoSQL也是分很多种类的,在NoSQL百花齐放的今天,NoSQL的正确选择比选择关系数据库还具有挑战性。虽然NoSQL的使用很简单,但是选择却是个麻烦事,这也正是很多人在观望的一个原因。

NoSQL的分类

NoSQL仅仅是一个概念,NoSQL数据库根据数据的存储模型和特点分为很多种类。 
这里写图片描述

以上NoSQL数据库类型的划分并不是绝对,只是从存储模型上来进行的大体划分。它们之间没有绝对的分界,也有交差的情况,比如Tokyo Cabinet / Tyrant的Table类型存储,就可以理解为是文档型存储,Berkeley DB XML数据库是基于Berkeley DB之上开发的。

NoSQL还是关系数据库 
虽然09年出现了比较激进的文章《关系数据库已死》,但是我们心里都清楚,关系数据库其实还活得好好的,你还不能不用关系数据库。但是也说明了一个事实,关系数据库在处理WEB2.0数据的时候,的确已经出现了瓶颈。

那么我们到底是用NoSQL还是关系数据库呢?我想我们没有必要来进行一个绝对的回答。我们需要根据我们的应用场景来决定我们到底用什么。

如果关系数据库在你的应用场景中,完全能够很好的工作,而你又是非常善于使用和维护关系数据库的,那么我觉得你完全没有必要迁移到NoSQL上面,除非你是个喜欢折腾的人。如果你是在金融,电信等以数据为王的关键领域,目前使用的是Oracle数据库来提供高可靠性的,除非遇到特别大的瓶颈,不然也别贸然尝试NoSQL。

然而,在WEB2.0的网站中,关系数据库大部分都出现了瓶颈。在磁盘IO、数据库可扩展上都花费了开发人员相当多的精力来优化,比如做分表分库(database sharding)、主从复制、异构复制等等,然而,这些工作需要的技术能力越来越高,也越来越具有挑战性。如果你正在经历这些场合,那么我觉得你应该尝试一下NoSQL了。

选择合适的NoSQL 
如此多类型的NoSQL,而每种类型的NoSQL又有很多,到底选择什么类型的NoSQL来作为我们的存储呢?这并不是一个很好回答的问题,影响我们选择的因素有很多,而选择也可能有多种,随着业务场景,需求的变更可能选择又会变化。我们常常需要根据如下情况考虑:

1.数据结构特点。包括结构化、半结构化、字段是否可能变更、是否有大文本字段、数据字段是否可能变化。

2.写入特点。包括insert比例、update比例、是否经常更新数据的某一个小字段、原子更新需求。

3.查询特点。包括查询的条件、查询热点的范围。比如用户信息的查询,可能就是随机的,而新闻的查询就是按照时间,越新的越频繁。

NoSQL和关系数据库结合 
其实NoSQL数据库仅仅是关系数据库在某些方面(性能,扩展)的一个弥补,单从功能上讲,NoSQL的几乎所有的功能,在关系数据库上都能够满足,所以选择NoSQL的原因并不在功能上。

所以,我们一般会把NoSQL和关系数据库进行结合使用,各取所长,需要使用关系特性的时候我们使用关系数据库,需要使用NoSQL特性的时候我们使用NoSQL数据库,各得其所。

举个简单的例子吧,比如用户评论的存储,评论大概有主键id、评论的对象aid、评论内容content、用户uid等字段。我们能确定的是评论内容content肯定不会在数据库中用where content=’’查询,评论内容也是一个大文本字段。那么我们可以把 主键id、评论对象aid、用户id存储在数据库,评论内容存储在NoSQL,这样数据库就节省了存储content占用的磁盘空间,从而节省大量IO,对content也更容易做Cache。

//从MySQL中查询出评论主键id列表 commentIds=DB.query(“SELECT id FROM comments where aid=’评论对象id’ LIMIT 0,20”); //根据主键id列表,从NoSQL取回评论实体数据 CommentsList=NoSQL.get(commentIds);NoSQL代替MySQL 
在某些应用场合,比如一些配置的关系键值映射存储、用户名和密码的存储、Session会话存储等等,用NoSQL完全可以替代MySQL存储。不但具有更高的性能,而且开发也更加方便。

NoSQL作为缓存服务器 
MySQL+Memcached的架构中,我们处处都要精心设计我们的缓存,包括过期时间的设计、缓存的实时性设计、缓存内存大小评估、缓存命中率等等。

NoSQL数据库一般都具有非常高的性能,在大多数场景下面,你不必再考虑在代码层为NoSQL构建一层Memcached缓存。NoSQL数据本身在Cache上已经做了相当多的优化工作。

Memcached这类内存缓存服务器缓存的数据大小受限于内存大小,如果用NoSQL来代替Memcached来缓存数据库的话,就可以不再受限于内存大小。虽然可能有少量的磁盘IO读写,可能比Memcached慢一点,但是完全可以用来缓存数据库的查询操作。

规避风险 
由于NoSQL是一个比较新的东西,特别是我们选择的NoSQL数据库还不是非常成熟的产品,所以我们可能会遇到未知的风险。为了得到NoSQL的好处,又要考虑规避风险,鱼与熊掌如何兼得?

现在业内很多公司的做法就是数据的备份。在往NoSQL里面存储数据的时候还会往MySQL里面存储一份。NoSQL数据库本身也需要进行备份(冷备和热备)。或者可以考虑使用两种NoSQL数据库,出现问题后可以进行切换(避免出现digg使用Cassandra的悲剧)。

总结 
本文只是简单的从MySQL和NoSQL的角度分析如何选择,以及进行融合使用。其实在选择NoSQL的时候,你可能还会碰到关于CAP原则,最终一致性,BASE思想的考虑。因为使用MySQL架构的时候,你也会碰到上面的问题,所以这里没有阐述。

转载自:http://blog.csdn.net/xlgen157387/article/details/48086607

1.命名规范

1.库名、表名、字段名必须使用小写字母,并采用下划线分割。 
a)MySQL有配置参数lower_case_table_names,不可动态更改,Linux系统默认为 0,即库表名以实际情况存储,大小写敏感。如果是1,以小写存储,大小写不敏感。如果是2,以实际情况存储,但以小写比较。 
b)如果大小写混合使用,可能存在abc,Abc,ABC等多个表共存,容易导致混乱。 
c)字段名显示区分大小写,但实际使⽤用不区分,即不可以建立两个名字一样但大小写不一样的字段。 
d)为了统一规范, 库名、表名、字段名使用小写字母。

2.库名、表名、字段名禁止超过32个字符。 
库名、表名、字段名支持最多64个字符,但为了统一规范、易于辨识以及减少传输量,禁止超过32个字符。

3.使用INNODB存储引擎。 
INNODB引擎是MySQL5.5版本以后的默认引擘,支持事务、行级锁,有更好的数据恢复能力、更好的并发性能,同时对多核、大内存、SSD等硬件支持更好,支持数据热备份等,因此INNODB相比MyISAM有明显优势。

4.库名、表名、字段名禁止使用mysql保留字。 
当库名、表名、字段名等属性含有保留字时,SQL语句必须用反引号引用属性名称,这将使得SQL语句书写、SHELL脚本中变量的转义等变得⾮非常复杂。

5.禁止使用分区表。 
分区表对分区键有严格要求;分区表在表变大后,执⾏行DDL、SHARDING、单表恢复等都变得更加困难。因此禁止使用分区表,并建议业务端手动SHARDING。

6.建议使用UNSIGNED存储非负数值。 
同样的字节数,非负存储的数值范围更大。如TINYINT有符号为 -128-127,无符号为0-255。

7.建议使用INT UNSIGNED存储IPV4。 
用UNSINGED INT存储IP地址占用4字节,CHAR(15)则占用15字节。另外,计算机处理整数类型比字符串类型快。使用INT UNSIGNED而不是CHAR(15)来存储IPV4地址,通过MySQL函数inet_ntoa和inet_aton来进行转化。IPv6地址目前没有转化函数,需要使用DECIMAL或两个BIGINT来存储。 
例如:

<code class="hljs sql has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;"><span class="hljs-operator" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">SELECT</span> INET_ATON(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">'209.207.224.40'</span>);</span> 3520061480 <span class="hljs-operator" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">SELECT</span> INET_NTOA(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">3520061480</span>);</span> 209.207.224.40</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li></ul>

8.强烈建议使用TINYINT来代替ENUM类型。 
ENUM类型在需要修改或增加枚举值时,需要在线DDL,成本较高;ENUM列值如果含有数字类型,可能会引起默认值混淆。

9.使用VARBINARY存储大小写敏感的变长字符串或二进制内容。 
VARBINARY默认区分大小写,没有字符集概念,速度快。

10.INT类型固定占用4字节存储 
例如INT(4)仅代表显示字符宽度为4位,不代表存储长度。数值类型括号后面的数字只是表示宽度而跟存储范围没有关系,比如INT(3)默认显示3位,空格补齐,超出时正常显示,PythonJava客户端等不具备这个功能。

11.区分使用DATETIME和TIMESTAMP。 
存储年使用YEAR类型。存储日期使用DATE类型。 存储时间(精确到秒)建议使用TIMESTAMP类型。 
DATETIME和TIMESTAMP都是精确到秒,优先选择TIMESTAMP,因为TIMESTAMP只有4个字节,而DATETIME8个字节。同时TIMESTAMP具有自动赋值以及⾃自动更新的特性。注意:在5.5和之前的版本中,如果一个表中有多个timestamp列,那么最多只能有一列能具有自动更新功能。

如何使用TIMESTAMP的自动赋值属性? 
a)自动初始化,而且自动更新:

<code class="hljs vbnet has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;">column1 TIMESTAMP <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">DEFAULT</span> CURRENT_TIMESTAMP <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">ON</span> UPDATECURRENT_TIMESTAMP</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li></ul>

b)只是自动初始化:

<code class="hljs php has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;"> column1 TIMESTAMP <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">DEFAULT</span> CURRENT_TIMESTAMP</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li></ul>

c)自动更新,初始化的值为0:

<code class="hljs sql has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;"> column1 TIMESTAMP DEFAULT 0 ON <span class="hljs-operator" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">UPDATE</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">CURRENT_TIMESTAMP</span></span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li></ul>

d)初始化的值为0:

<code class="hljs php has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;">column1 TIMESTAMP <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">DEFAULT</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li></ul>

12.所有字段均定义为NOT NULL。 
a)对表的每一行,每个为NULL的列都需要额外的空间来标识。 
b)B树索引时不会存储NULL值,所以如果索引字段可以为NULL,索引效率会下降。 
c)建议用0、特殊值或空串代替NULL值。

MySQL使用技巧

1.将大字段、访问频率低的字段拆分到单独的表中存储,分离冷热数据。 
有利于有效利用缓存,防⽌止读入无用的冷数据,较少磁盘IO,同时保证热数据常驻内存提⾼高缓存命中率。

2.禁止在数据库中存储明文密码。 
采用加密字符串存储密码,并保证密码不可解密,同时采用随机字符串加盐保证密码安全。

3.表必须有主键,推荐使用UNSIGNED自增列作为主键。 
表没有主键,INNODB会默认设置隐藏的主键列;没有主键的表在定位数据行的时候非常困难,也会降低基于行复制的效率。

4.禁止冗余索引。 
索引是双刃剑,会增加维护负担,增⼤大IO压力。(a,b,c)、(a,b),后者为冗余索引。可以利用前缀索引来达到加速目的,减轻维护负担。

5.禁止重复索引。 
primary key a;uniq index a;重复索引增加维护负担、占用磁盘空间,同时没有任何益处。

6.不在低基数列上建立索引,例如“性别”。 
大部分场景下,低基数列上建立索引的精确查找,相对于不建立索引的全表扫描没有任何优势,而且增大了IO负担。

7.合理使用覆盖索引减少IO,避免排序。 
覆盖索引能从索引中获取需要的所有字段,从⽽而避免回表进行二次查找,节省IO。 
INNODB存储引擎中,secondary index(非主键索引,又称为辅助索引、二级索引)没有直接存储行地址,而是存储主键值。 
如果用户需要查询secondary index中所不包含的数据列,则需要先通过secondary index查找到主键值,然后再通过主键查询到其他数据列,因此需要查询两次。覆盖索引则可以在⼀一个索引中获取所有需要的数据,因此效率较高。 
例如SELECT email,uid FROM user_email WHERE uid=xx,如果uid不是主键,适当时候可以将索引添加为index(uid,email),以获得性能提升。

8.用IN代替OR。SQL语句中IN包含的值不应过多,应少于1000个。 
IN是范围查找,MySQL内部会对IN的列表值进行排序后查找,比OR效率更高。

9.表字符集使用UTF8,必要时可申请使用UTF8MB4字符集。 
a)UTF8字符集存储汉字占用3个字节,存储英文字符占用一个字节。 
b)UTF8统一而且通用,不会出现转码出现乱码风险。 
c)如果遇到EMOJ等表情符号的存储需求,可申请使用UTF8MB4字符集。

10.用UNION ALL代替UNION。 
UNION ALL不需要对结果集再进行排序。

11.禁止使用order by rand()。 
order by rand()会为表增加一个伪列,然后用rand()函数为每一行数据计算出rand()值,然后基于该行排序,这通常都会生成磁盘上的临时表,因此效率非常低。建议先使用rand()函数获得随机的主键值,然后通过主键 
获取数据。

12.建议使用合理的分页方式以提高分页效率。 
假如有类似下面分页语句:

<code class="hljs sql has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;"><span class="hljs-operator" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">SELECT</span> * <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">FROM</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">table</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">ORDER</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">BY</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">TIME</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">DESC</span> LIMIT <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">10000</span>,<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">10</span>;</span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li></ul>

这种分页方式会导致大量的io,因为MySQL使用的是提前读取策略。 
推荐分页方式:

<code class="hljs sql has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;"><span class="hljs-operator" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">SELECT</span> * <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">FROM</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">table</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">WHERE</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">TIME</span><last_TIME <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">ORDER</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">BY</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">TIME</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">DESC</span> LIMIT <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">10.</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">SELECT</span> * <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">FROM</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">table</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">inner</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">JOIN</span> (<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">SELECT</span> id <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">FROM</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">table</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">ORDER</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">BY</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">TIME</span> LIMIT <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">10000</span>,<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">10</span>) <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">as</span> t <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">USING</span>(id)</span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li></ul>

13.SELECT只获取必要的字段,禁⽌止使用SELECT *。 
减少网络带宽消耗; 
能有效利用覆盖索引; 
表结构变更对程序基本无影响。

14.SQL中避免出现now()、rand()、sysdate()、current_user()等不确定结果的函数。 
语句级复制场景下,引起主从数据不一致;不确定值的函数,产⽣生的SQL语句无法利用QUERY CACHE。

15.采用合适的分库分表策略。例如千库十表、十库百表等。 
采用合适的分库分表策略,有利于业务发展后期快速对数据库进行水平拆分,同时分库可以有效利⽤用MySQL 
的多线程复制特性。

16.减少与数据库交互次数,尽量采用批量SQL语句。 
使用下面的语句来减少和db的交互次数:

<code class="hljs sql has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;">a)<span class="hljs-operator" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">INSERT</span> ... <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">ON</span> DUPLICATE <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">KEY</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">UPDATE</span> b)<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">REPLACE</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">INTO</span> c)<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">INSERT</span> IGNORE d)<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">INSERT</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">INTO</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">VALUES</span>() </span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li></ul>

17.拆分复杂SQL为多个小SQL,避免大事务。 
简单的SQL容易使⽤用到MySQL的QUERY CACHE;减少锁表时间特别是MyISAM;可以使用多核 CPU。

18.对同一个表的多次alter操作必须合并为一次操作。 
mysql对表的修改绝大部分操作都需要锁表并重建表,而锁表则会对线上业务造成影响。为减少这种影响,必须把对表的多次alter操作合并为一次操作。例如,要给表t增加一个字段b,同时给已有的字段aa建立索引, 
通常的做法分为两步:

<code class="hljs sql has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;"><span class="hljs-operator" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">alter</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">table</span> t <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">add</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">column</span> b <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">varchar</span>(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">10</span>);</span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li></ul>

然后增加索引:

<code class="hljs sql has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;"><span class="hljs-operator" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">alter</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">table</span> t <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">add</span> index idx_aa(aa);</span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li></ul>

正确的做法是:

<code class="hljs sql has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;"><span class="hljs-operator" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">alter</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">table</span> t <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">add</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">column</span> b <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">varchar</span>(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">10</span>),<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">add</span> index idx_aa(aa);</span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li></ul>

19.避免使用存储过程、触发器、视图、自定义函数等。 
这些高级特性有性能问题,以及未知BUG较多。业务逻辑放到数据库会造成数据库的DDL、SCALE OUT、 
SHARDING等变得更加困难。

20.禁止有super权限的应用程序账号存在。 
安全第一。super权限会导致read only失效,导致较多诡异问题而且很难追踪。

21.不要在MySQL数据库中存放业务逻辑。 
数据库是有状态的服务,变更复杂而且速度慢,如果把业务逻辑放到数据库中,将会限制业务的快速发展。建议把业务逻辑提前,放到前端或中间逻辑层,而把数据库作为存储层,实现逻辑与存储的分离。

猜你喜欢

转载自blog.csdn.net/Scrat_Kong/article/details/82113897