简介 分区表是在SQL SERVER2005之后的版本引入的特性。这个特性允许把逻辑上的一个表在物理上分为很多部分。而对于SQL SERVER2005之前版本,所谓的分区表仅仅是分布式视图,也就是多个表做union操作. 分区表在逻辑上是一个表,而物理上是多个表.这意味着从用户的角度来看,分区表和普通表是一样的。这个概念可以简单如下图所示: 而对于SQL SERVER2005之前的版本,是没有分区这个概念的,所谓的分区仅仅是分布式视图: 本篇文章所讲述的分区表指的是SQL SERVER2005之后引入的分区表特性. 为什么要对表进行分区 在回答标题的问题之前,需要说明的是,表分区这个特性只有在企业版或者开发版中才有,还有理解表分区的概念还需要理解SQL SERVER中文件和文件组的概念. 对表进行分区在多种场景下都需要被用到.通常来说,使用表分区最主要是用于: 存档,比如将销售记录中1年前的数据分到一个专门存档的服务器中 便于管理,比如把一个大表分成若干个小表,则备份和恢复的时候不再需要备份整个表,可以单独备份分区 提高可用性,当一个分区跪了以后,只有一个分区不可用,其它分区不受影响 提高性能,这个往往是大多数人分区的目的,把一个表分布到不同的硬盘或其他存储介质中,会大大提升查询的速度. 分区表的步骤 分区表的定义大体上分为三个步骤: 定义分区函数 定义分区构架 定义分区表 分区函数,分区构架和分区表的关系如下: 分区表依赖分区构架,而分区构架又依赖分区函数.值得注意的是,分区函数并不属于具体的分区构架和分区表,他们之间的关系仅仅是使用关系. 下面我们通过一个例子来看如何定义一个分区表: 假设我们需要定义的分区表结构如下: 第一列为自增列,orderid为订单id列,SalesDate为订单日期列,也就是我们需要分区的依据. 下面我们按照上面所说的三个步骤来实现分区表. 定义分区函数 分区函数是用于判定数据行该属于哪个分区,通过分区函数中设置边界值来使得根据行中特定列的值来确定其分区,上面例子中,我们可以通过SalesDate的值来判定其不同的分区.假设我们想定义两个边界值(boundaryValue)进行分区,则会生成三个分区,这里我设置边界值分别为2004-01-01和2007-01-01,则前面例子中的表会根据这两个边界值分成三个区: 在MSDN中,定义分区函数的原型如下:
1 2 3 4 |
<a href="http://search.microsoft.com/default.asp?so=RECCNT&siteid=us%2Fdev&p=1&nq=NEW&qu=CREATE&IntlSearch=&boolean=PHRASE&ig=01&i=09&i=99">CREATE</a> PARTITION <a href="http://search.microsoft.com/default.asp?so=RECCNT&siteid=us%2Fdev&p=1&nq=NEW&qu=FUNCTION&IntlSearch=&boolean=PHRASE&ig=01&i=09&i=99">FUNCTION</a> partition_function_name ( input_parameter_type ) <a href="http://search.microsoft.com/default.asp?so=RECCNT&siteid=us%2Fdev&p=1&nq=NEW&qu=AS&IntlSearch=&boolean=PHRASE&ig=01&i=09&i=99">AS</a> RANGE [ <a href="http://search.microsoft.com/default.asp?so=RECCNT&siteid=us%2Fdev&p=1&nq=NEW&qu=LEFT&IntlSearch=&boolean=PHRASE&ig=01&i=09&i=99">LEFT</a> | <a href="http://search.microsoft.com/default.asp?so=RECCNT&siteid=us%2Fdev&p=1&nq=NEW&qu=RIGHT&IntlSearch=&boolean=PHRASE&ig=01&i=09&i=99">RIGHT</a> ] <a href="http://search.microsoft.com/default.asp?so=RECCNT&siteid=us%2Fdev&p=1&nq=NEW&qu=FOR&IntlSearch=&boolean=PHRASE&ig=01&i=09&i=99">FOR</a> <a href="http://search.microsoft.com/default.asp?so=RECCNT&siteid=us%2Fdev&p=1&nq=NEW&qu=VALUES&IntlSearch=&boolean=PHRASE&ig=01&i=09&i=99">VALUES</a> ( [ boundary_value [ ,...n ] ] ) [ ; ] |
通过定义分区函数的原型,我们看出其中并没有具体涉及具体的表.因为分区函数并不和具体的表相绑定.上面原型中还可以看到Range left和right.这个参数是决定临界值本身应该归于“left”还是“right”: 下面我们根据上面的参数定义分区函数: 通过系统视图,可以看见这个分区函数已经创建成功 定义分区构架 定义完分区函数仅仅是知道了如何将列的值区分到了不同的分区。而每个分区的存储方式,则需要分区构架来定义.使用分区构架需要你对文件和文件组有点了解. 我们先来看MSDN的分区构架的原型:
1 2 3 4 |
<a href="http://search.microsoft.com/default.asp?so=RECCNT&siteid=us%2Fdev&p=1&nq=NEW&qu=CREATE&IntlSearch=&boolean=PHRASE&ig=01&i=09&i=99">CREATE</a> PARTITION SCHEME partition_scheme_name <a href="http://search.microsoft.com/default.asp?so=RECCNT&siteid=us%2Fdev&p=1&nq=NEW&qu=AS&IntlSearch=&boolean=PHRASE&ig=01&i=09&i=99">AS</a> PARTITION partition_function_name [ <a href="http://search.microsoft.com/default.asp?so=RECCNT&siteid=us%2Fdev&p=1&nq=NEW&qu=ALL&IntlSearch=&boolean=PHRASE&ig=01&i=09&i=99">ALL</a> ] <a href="http://search.microsoft.com/default.asp?so=RECCNT&siteid=us%2Fdev&p=1&nq=NEW&qu=TO&IntlSearch=&boolean=PHRASE&ig=01&i=09&i=99">TO</a> ( { file_group_name | [ <a href="http://search.microsoft.com/default.asp?so=RECCNT&siteid=us%2Fdev&p=1&nq=NEW&qu=PRIMARY&IntlSearch=&boolean=PHRASE&ig=01&i=09&i=99">PRIMARY</a> ] } [ ,...n ] ) [ ; ] |
从原型来看,分区构架仅仅是依赖分区函数.分区构架中负责分配每个区属于哪个文件组,而分区函数是决定如何在逻辑上分区: 基于之前创建的分区函数,创建分区构架: 定义分区表 接下来就该创建分区表了.表在创建的时候就已经决定是否是分区表了。虽然在很多情况下都是你在发现已经表已经足够大的时候才想到要把表分区,但是分区表只能够在创建的时候指定为分区表。 为刚建立的分区表PartitionedTable加入5万条测试数据,其中SalesDate随机生成,从2001年到2010年随机分布.加入数据后,我们通过如下语句来看结果:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
<a href="http://search.microsoft.com/default.asp?so=RECCNT&siteid=us%2Fdev&p=1&nq=NEW&qu=select&IntlSearch=&boolean=PHRASE&ig=01&i=09&i=99">select</a> <a href="http://search.microsoft.com/default.asp?so=RECCNT&siteid=us%2Fdev&p=1&nq=NEW&qu=convert&IntlSearch=&boolean=PHRASE&ig=01&i=09&i=99">convert</a>(<a href="http://search.microsoft.com/default.asp?so=RECCNT&siteid=us%2Fdev&p=1&nq=NEW&qu=varchar&IntlSearch=&boolean=PHRASE&ig=01&i=09&i=99">varchar</a>(50), ps.name) <a href="http://search.microsoft.com/default.asp?so=RECCNT&siteid=us%2Fdev&p=1&nq=NEW&qu=as&IntlSearch=&boolean=PHRASE&ig=01&i=09&i=99">as</a> partition_scheme, p.partition_number, <a href="http://search.microsoft.com/default.asp?so=RECCNT&siteid=us%2Fdev&p=1&nq=NEW&qu=convert&IntlSearch=&boolean=PHRASE&ig=01&i=09&i=99">convert</a>(<a href="http://search.microsoft.com/default.asp?so=RECCNT&siteid=us%2Fdev&p=1&nq=NEW&qu=varchar&IntlSearch=&boolean=PHRASE&ig=01&i=09&i=99">varchar</a>(10), ds2.name) <a href="http://search.microsoft.com/default.asp?so=RECCNT&siteid=us%2Fdev&p=1&nq=NEW&qu=as&IntlSearch=&boolean=PHRASE&ig=01&i=09&i=99">as</a> filegroup, <a href="http://search.microsoft.com/default.asp?so=RECCNT&siteid=us%2Fdev&p=1&nq=NEW&qu=convert&IntlSearch=&boolean=PHRASE&ig=01&i=09&i=99">convert</a>(<a href="http://search.microsoft.com/default.asp?so=RECCNT&siteid=us%2Fdev&p=1&nq=NEW&qu=varchar&IntlSearch=&boolean=PHRASE&ig=01&i=09&i=99">varchar</a>(19), isnull(v.<a href="http://search.microsoft.com/default.asp?so=RECCNT&siteid=us%2Fdev&p=1&nq=NEW&qu=value&IntlSearch=&boolean=PHRASE&ig=01&i=09&i=99">value</a>, ''), 120) <a href="http://search.microsoft.com/default.asp?so=RECCNT&siteid=us%2Fdev&p=1&nq=NEW&qu=as&IntlSearch=&boolean=PHRASE&ig=01&i=09&i=99">as</a> range_boundary, str(p.<a href="http://search.microsoft.com/default.asp?so=RECCNT&siteid=us%2Fdev&p=1&nq=NEW&qu=rows&IntlSearch=&boolean=PHRASE&ig=01&i=09&i=99">rows</a>, 9) <a href="http://search.microsoft.com/default.asp?so=RECCNT&siteid=us%2Fdev&p=1&nq=NEW&qu=as&IntlSearch=&boolean=PHRASE&ig=01&i=09&i=99">as</a> <a href="http://search.microsoft.com/default.asp?so=RECCNT&siteid=us%2Fdev&p=1&nq=NEW&qu=rows&IntlSearch=&boolean=PHRASE&ig=01&i=09&i=99">rows</a> <a href="http://search.microsoft.com/default.asp?so=RECCNT&siteid=us%2Fdev&p=1&nq=NEW&qu=from&IntlSearch=&boolean=PHRASE&ig=01&i=09&i=99">from</a> sys.indexes i <a href="http://search.microsoft.com/default.asp?so=RECCNT&siteid=us%2Fdev&p=1&nq=NEW&qu=join&IntlSearch=&boolean=PHRASE&ig=01&i=09&i=99">join</a> sys.partition_schemes ps <a href="http://search.microsoft.com/default.asp?so=RECCNT&siteid=us%2Fdev&p=1&nq=NEW&qu=on&IntlSearch=&boolean=PHRASE&ig=01&i=09&i=99">on</a> i.data_space_id = ps.data_space_id <a href="http://search.microsoft.com/default.asp?so=RECCNT&siteid=us%2Fdev&p=1&nq=NEW&qu=join&IntlSearch=&boolean=PHRASE&ig=01&i=09&i=99">join</a> sys.destination_data_spaces dds <a href="http://search.microsoft.com/default.asp?so=RECCNT&siteid=us%2Fdev&p=1&nq=NEW&qu=on&IntlSearch=&boolean=PHRASE&ig=01&i=09&i=99">on</a> ps.data_space_id = dds.partition_scheme_id <a href="http://search.microsoft.com/default.asp?so=RECCNT&siteid=us%2Fdev&p=1&nq=NEW&qu=join&IntlSearch=&boolean=PHRASE&ig=01&i=09&i=99">join</a> sys.data_spaces ds2 <a href="http://search.microsoft.com/default.asp?so=RECCNT&siteid=us%2Fdev&p=1&nq=NEW&qu=on&IntlSearch=&boolean=PHRASE&ig=01&i=09&i=99">on</a> dds.data_space_id = ds2.data_space_id <a href="http://search.microsoft.com/default.asp?so=RECCNT&siteid=us%2Fdev&p=1&nq=NEW&qu=join&IntlSearch=&boolean=PHRASE&ig=01&i=09&i=99">join</a> sys.partitions p <a href="http://search.microsoft.com/default.asp?so=RECCNT&siteid=us%2Fdev&p=1&nq=NEW&qu=on&IntlSearch=&boolean=PHRASE&ig=01&i=09&i=99">on</a> dds.destination_id = p.partition_number <a href="http://search.microsoft.com/default.asp?so=RECCNT&siteid=us%2Fdev&p=1&nq=NEW&qu=and&IntlSearch=&boolean=PHRASE&ig=01&i=09&i=99">and</a> p.object_id = i.object_id <a href="http://search.microsoft.com/default.asp?so=RECCNT&siteid=us%2Fdev&p=1&nq=NEW&qu=and&IntlSearch=&boolean=PHRASE&ig=01&i=09&i=99">and</a> p.index_id = i.index_id <a href="http://search.microsoft.com/default.asp?so=RECCNT&siteid=us%2Fdev&p=1&nq=NEW&qu=join&IntlSearch=&boolean=PHRASE&ig=01&i=09&i=99">join</a> sys.partition_functions pf <a href="http://search.microsoft.com/default.asp?so=RECCNT&siteid=us%2Fdev&p=1&nq=NEW&qu=on&IntlSearch=&boolean=PHRASE&ig=01&i=09&i=99">on</a> ps.function_id = pf.function_id <a href="http://search.microsoft.com/default.asp?so=RECCNT&siteid=us%2Fdev&p=1&nq=NEW&qu=LEFT&IntlSearch=&boolean=PHRASE&ig=01&i=09&i=99">LEFT</a> <a href="http://search.microsoft.com/default.asp?so=RECCNT&siteid=us%2Fdev&p=1&nq=NEW&qu=JOIN&IntlSearch=&boolean=PHRASE&ig=01&i=09&i=99">JOIN</a> sys.Partition_Range_values v <a href="http://search.microsoft.com/default.asp?so=RECCNT&siteid=us%2Fdev&p=1&nq=NEW&qu=on&IntlSearch=&boolean=PHRASE&ig=01&i=09&i=99">on</a> pf.function_id = v.function_id <a href="http://search.microsoft.com/default.asp?so=RECCNT&siteid=us%2Fdev&p=1&nq=NEW&qu=and&IntlSearch=&boolean=PHRASE&ig=01&i=09&i=99">and</a> v.boundary_id = p.partition_number - pf.boundary_value_on_right <a href="http://search.microsoft.com/default.asp?so=RECCNT&siteid=us%2Fdev&p=1&nq=NEW&qu=WHERE&IntlSearch=&boolean=PHRASE&ig=01&i=09&i=99">WHERE</a> i.object_id = object_id('PartitionedTable') <a href="http://search.microsoft.com/default.asp?so=RECCNT&siteid=us%2Fdev&p=1&nq=NEW&qu=and&IntlSearch=&boolean=PHRASE&ig=01&i=09&i=99">and</a> i.index_id <a href="http://search.microsoft.com/default.asp?so=RECCNT&siteid=us%2Fdev&p=1&nq=NEW&qu=in&IntlSearch=&boolean=PHRASE&ig=01&i=09&i=99">in</a> (0, 1) <a href="http://search.microsoft.com/default.asp?so=RECCNT&siteid=us%2Fdev&p=1&nq=NEW&qu=order&IntlSearch=&boolean=PHRASE&ig=01&i=09&i=99">order</a> <a href="http://search.microsoft.com/default.asp?so=RECCNT&siteid=us%2Fdev&p=1&nq=NEW&qu=by&IntlSearch=&boolean=PHRASE&ig=01&i=09&i=99">by</a> p.partition_number |
可以看到我们分区的数据分布: 分区表的分割 分区表的分割。相当于新建一个分区,将原有的分区需要分割的内容插入新的分区,然后删除老的分区的内容,概念如下图: 假设我新加入一个分割点:2009-01-01,则概念如下: 通过上图我们可以看出,如果分割时,被分割的分区3内有内容需要分割到分区4,则这些数据需要被复制到分区4,并删除分区3上对应数据。 这种操作非常非常消耗IO,并且在分割的过程中锁定分区三内的内容,造成分区三的内容不可用。不仅仅如此,这个操作生成的日志内容会是被转移数据的4倍! 所以我们如果不想因为这种操作给客户带来麻烦而被老板爆菊的话…最好还是把分割点建立在未来(也就是预先建立分割点),比如2012-01-01。则分区3内的内容不受任何影响。在以后2012的数据加入时,自动插入到分区4. 分割现有的分区需要两个步骤: 1.首先告诉SQL SERVER新建立的分区放到哪个文件组 2.建立新的分割点 可以通过如下语句来完成: 如果我们的分割构架在定义的时候已经指定了NEXT USED,则直接添加分割点即可。 通过文中前面查看分区的长语句..再来看: 新的分区已经加入! […]
View Details写在前面:上次我关于索引的文章有几个园友发站内信问我如何将索引和表存储在不同的硬盘上。我觉的需要专门写一篇文章来讲述一下文件和文件组应该更容易理解. 简介 在SQL SERVER中,数据库在硬盘上的存储方式和普通文件在Windows中的存储方式没有什么不同,仅仅是几个文件而已.SQL SERVER通过管理逻辑上的文件组的方式来管理文件.理解文件和文件组的概念对于更好的配置数据库来说是最基本的知识。 理解文件和文件组 在SQL SERVER中,通过文件组这个逻辑对象对存放数据的文件进行管理. 先来看一张图: 我们看到的逻辑数据库由一个或者多个文件组构成 而文件组管理着磁盘上的文件.而文件中存放着SQL SERVER的实际数据. 为什么通过文件组来管理文件 对于用户角度来说,需对创建的对象指定存储的文件组只有三种数据对象:表,索引和大对象(LOB) 使用文件组可以隔离用户和文件,使得用户针对文件组来建立表和索引,而不是实际磁盘中的文件。当文件移动或修改时,由于用户建立的表和索引是建立在文件组上的,并不依赖具体文件,这大大加强了可管理性. 还有一点是,使用文件组来管理文件可以使得同一文件组内的不同文件分布在不同的硬盘中,极大的提高了IO性能. SQL SERVER会根据每个文件设置的初始大小和增长量会自动分配新加入的空间,假设在同一文件组中的文件A设置的大小为文件B的两倍,新增一个数据占用三页(Page),则按比例将2页分配到文件A中,1页分配到文件B中. 文件的分类 首要文件:这个文件是必须有的,而且只能有一个。这个文件额外存放了其他文件的位置等信息.扩展名为.mdf 次要文件:可以建任意多个,用于不同目的存放.扩展名为.ndf 日志文件:存放日志,扩展名为.ldf 在SQL SERVER 2008之后,还新增了文件流数据文件和全文索引文件. 上述几种文件名扩展名可以随意修改,但是我推荐使用默认的扩展名。 我们可以通过如下语句查看数据库中的文件情况: 还有一点要注意的是,如果一个表是存在物理上的多个文件中时,则表的数据页的组织为N(N为具体的几个文件)个B树.而不是一个对象为一个B树. 创建和使用文件组 创建文件或是文件组可以通过在SSMS中或者使用T-SQL语句进行。对于一个数据库来说,既可以在创建时增加文件和文件组,也可以向现有的数据库添加文件和文件组.这几种方式大同小异.下面来看一下通过SSMS向现有数据库添加文件和文件组. 首先创建文件组: 文件组创建好后就可以向现有文件组中添加文件了: 下面我们就可以通过语句将创建的表或者索引加入到新的文件组中了: 使用多个文件的优点与缺点 通常情况下,小型的数据库并不需要创建多个文件来分布数据。但是随着数据的增长,使用单个文件的弊端就开始显现。 首先:使用多个文件分布数据到多个硬盘中可以极大的提高IO性能. 其次:多个文件对于数据略多的数据库来说,备份和恢复都会轻松很多.我碰见过遇到一个150G的数据库,手头却没有这么大的存储设备… 但是,在数据库的世界中,每一项好处往往伴随着一个坏处: 显而易见,使用多文件需要占用更多的磁盘空间。这是因为每个文件中都有自己的一套B树组织方式,和自己的增长空间。当然了,还有一套自己的碎片-.-但是在大多数情况下,多占点磁盘空间带来的弊端要远远小于多文件带来的好处. 总结 本文对SQL SERVER中文件和文件组的概念进行了简单阐述,并在文中讲述了文件和文件组的配置方式。按照业务组织好不同的文件组来分布不同的文件,使得性能的提升,对于你半夜少接几个电话的帮助是灰常大滴:-) from:http://www.cnblogs.com/CareySon/archive/2011/12/26/2301597.html
View Details我谈到了一些关于ASP.NET Forms身份认证方面的话题,这次的博客将主要介绍ASP.NET Windows身份认证。 Forms身份认证虽然使用广泛,不过,如果是在 Windows Active Directory 的环境中使用ASP.NET, 那么使用Windows身份认证也会比较方便。 方便性表现为:我们不用再设计登录页面,不用编写登录验证逻辑。而且使用Windows身份认证会有更好的安全保障。 回到顶部 认识ASP.NET Windows身份认证 要使用Windows身份认证模式,需要在web.config设置:
1 |
<authentication mode="Windows" /> |
Windows身份认证做为ASP.NET的默认认证方式,与Forms身份认证在许多基础方面是一样的。 上篇博客我说过:我认为ASP.NET的身份认证的最核心部分其实就是HttpContext.User这个属性所指向的对象。 在接下来的部分,我将着重分析这个对象在二种身份认证中有什么差别。 在ASP.NET身份认证过程中,IPrincipal和IIdentity这二个接口有着非常重要的作用。 前者定义用户对象的基本功能,后者定义标识对象的基本功能, 不同的身份认证方式得到的这二个接口的实例也是不同的。 ASP.NET Windows身份认证是由WindowsAuthenticationModule实现的。 WindowsAuthenticationModule在ASP.NET管线的AuthenticateRequest事件中, 使用从IIS传递到ASP.NET的Windows访问令牌(Token)创建一个WindowsIdentity对象,Token通过调用context.WorkerRequest.GetUserToken()获得, 然后再根据WindowsIdentity 对象创建WindowsPrincipal对象, 然后把它赋值给HttpContext.User。 在Forms身份认证中,我们需要创建登录页面,让用户提交用户名和密码,然后检查用户名和密码的正确性, 接下来创建一个包含FormsAuthenticationTicket对象的登录Cookie供后续请求使用。 FormsAuthenticationModule在ASP.NET管线的AuthenticateRequest事件中, 解析登录Cookie并创建一个包含FormsIdentity的GenericPrincipal对象, 然后把它赋值给HttpContext.User。 上面二段话简单了概括了二种身份认证方式的工作方式。 我们可以发现它们存在以下差别: 1. Forms身份认证需要Cookie表示登录状态,Windows身份认证则依赖于IIS 2. Windows身份认证不需要我们设计登录页面,不用编写登录验证逻辑,因此更容易使用。 在授权阶段,UrlAuthorizationModule仍然会根据当前用户检查将要访问的资源是否得到许可。 接下来,FileAuthorizationModule检查 HttpContext.User.Identity 属性中的 IIdentity 对象是否是 WindowsIdentity 类的一个实例。 如果 IIdentity 对象不是 WindowsIdentity 类的一个实例,则 FileAuthorizationModule 类停止处理。 如果存在 WindowsIdentity 类的一个实例,则 FileAuthorizationModule 类调用 AccessCheck Win32 函数(通过 P/Invoke) 来确定是否授权经过身份验证的客户端访问请求的文件。 如果该文件的安全描述符的随机访问控制列表 (DACL) 中至少包含一个 Read 访问控制项 (ACE),则允许该请求继续。 否则,FileAuthorizationModule 类调用 HttpApplication.CompleteRequest 方法并将状态码 401 返回到客户端。 在Windows身份认证中,验证工作主要是由IIS实现的,WindowsAuthenticationModule其实只是负责创建WindowsPrincipal和WindowsIdentity而已。 顺便介绍一下:Windows 身份验证又分为“NTLM 身份验证”和“Kerberos v5 身份验证”二种, 关于这二种Windows身份认证的更多说明可查看MSDN技术文章:解释:ASP.NET 2.0 中的 Windows 身份验证。 在我看来,IIS最终使用哪种Windows身份认证方式并不影响我们的开发过程,因此本文不会讨论这个话题。 根据我的实际经验来看,使用Windows身份认证时,主要的开发工作将是根据登录名从Active Directory获取用户信息。 […]
View Details一、 MySQL: 索引以B树格式保存 Memory存储引擎可以选择Hash或BTree索引,Hash索引只能用于=或<=>的等式比较。 1、普通索引:create index on Tablename(列的列表) alter table TableName add index (列的列表) create table TableName([…], index [IndexName] (列的列表) 2、唯一性索引:create unique index alter … add unique 主键:一种唯一性索引,必须指定为primary key 3、全文索引:从3.23.23版开始支持全文索引和全文检索,FULLTEXT, 可以在char、varchar或text类型的列上创建。 4、单列索引、多列索引: 多个单列索引与单个多列索引的查询效果不同,因为: 执行查询时,MySQL只能使用一个索引,会从多个索引中选择一个限制最为严格的索引。 5、最左前缀(Leftmost Prefixing):多列索引,例如:fname_lname_age索引,以下的搜索条件MySQL都将使用 fname_lname_age索引:firstname,lastname,age;firstname,lastname;firstname,其他情况将不使用。 二、根据sql查询语句确定创建哪种类型的索引,如何优化查询 选择索引列: a.性能优化过程中,选择在哪个列上创建索引是最重要的步骤之一。可以考虑使用索引的主要有 两种类型的列:在where子句中出现的列,在join子句中出现的列。 b.考虑列中值的分布,索引的列的基数越大,索引的效果越好。 c.使用短索引,如果对字符串列进行索引,应该指定一个前缀长度,可节省大量索引空间,提升查询速度。 d.利用最左前缀 e.不要过度索引,只保持所需的索引。每个额外的索引都要占用额外的磁盘空间,并降低写操作的性能。 在修改表的内容时,索引必须进行更新,有时可能需要重构,因此,索引越多,所花的时间越长。 MySQL只对一下操作符才使用索引:<,<=,=,>,>=,between,in, 以及某些时候的like(不以通配符%或_开头的情形)。 from:http://database.51cto.com/art/200905/122789.htm
View DetailsMyISAM 是MySQL中默认的存储引擎,一般来说不是有太多人关心这个东西。决定使用什么样的存储引擎是一个很tricky的事情,但是还是值我们去研究一下,这里的文章只考虑 MyISAM 和InnoDB这两个,因为这两个是最常见的。 下面先让我们回答一些问题: ◆你的数据库有外键吗? ◆你需要事务支持吗? ◆你需要全文索引吗? ◆你经常使用什么样的查询模式? ◆你的数据有多大? 思考上面这些问题可以让你找到合适的方向,但那并不是绝对的。如果你需要事务处理或是外键,那么InnoDB 可能是比较好的方式。如果你需要全文索引,那么通常来说 MyISAM是好的选择,因为这是系统内建的,然而,我们其实并不会经常地去测试两百万行记录。所以,就算是慢一点,我们可以通过使用Sphinx从InnoDB中获得全文索引。 数据的大小,是一个影响你选择什么样存储引擎的重要因素,大尺寸的数据集趋向于选择InnoDB方式,因为其支持事务处理和故障恢复。数据库的大小决定了故障恢复的时间长短,InnoDB可以利用事务日志进行数据恢复,这会比较快。而MyISAM可能会需要几个小时甚至几天来干这些事,InnoDB只需要几分钟。 您操作数据库表的习惯可能也会是一个对性能影响很大的因素。比如: COUNT() 在 MyISAM 表中会非常快,而在InnoDB 表下可能会很痛苦。而主键查询则在InnoDB下会相当相当的快,但需要小心的是如果我们的主键太长了也会导致性能问题。大批的inserts 语句在MyISAM下会快一些,但是updates 在InnoDB 下会更快一些——尤其在并发量大的时候。 所以,到底你检使用哪一个呢?根据经验来看,如果是一些小型的应用或项目,那么MyISAM 也许会更适合。当然,在大型的环境下使用MyISAM 也会有很大成功的时候,但却不总是这样的。如果你正在计划使用一个超大数据量的项目,而且需要事务处理或外键支持,那么你真的应该直接使用InnoDB方式。但需要记住InnoDB 的表需要更多的内存和存储,转换100GB 的MyISAM 表到InnoDB 表可能会让你有非常坏的体验。 from:http://database.51cto.com/art/200905/122382.htm
View Details什么是数据库分区? 数据库分区是一种物理数据库设计技术,DBA和数据库建模人员对其相当熟悉。虽然分区技术可以实现很多效果,但其主要目的是为了在特定的SQL操作中减少数据读写的总量以缩减响应时间。 分区主要有两种形式://这里一定要注意行和列的概念(row是行,column是列) 1. 水平分区(Horizontal Partitioning)这种形式分区是对表的行进行分区,通过这样的方式不同分组里面的物理列分割的数据集得以组合,从而进行个体分割(单分区)或集体分割(1个或多个分区)。所有在表中定义的列在每个数据集中都能找到,所以表的特性依然得以保持。 举个简单例子:一个包含十年发票记录的表可以被分区为十个不同的分区,每个分区包含的是其中一年的记录。(朋奕注:这里具体使用的分区方式我们后面再说,可以先说一点,一定要通过某个属性列来分割,譬如这里使用的列就是年份) 2. 垂直分区(Vertical Partitioning) 这种分区方式一般来说是通过对表的垂直划分来减少目标表的宽度,使某些特定的列 被划分到特定的分区,每个分区都包含了其中的列所对应的行。 举个简单例子:一个包含了大text和BLOB列的表,这些text和BLOB列又不经常被访问,这时候就要把这些不经常使用的text和BLOB了划分到另一个分区,在保证它们数据相关性的同时还能提高访问速度。 在数据库供应商开始在他们的数据库引擎中建立分区(主要是水平分区)时,DBA和建模者必须设计好表的物理分区结构,不要保存冗余的数据(不同表中同时都包含父表中的数据)或相互联结成一个逻辑父对象(通常是视图)。这种做法会使水平分区的大部分功能失效,有时候也会对垂直分区产生影响。 在MySQL 5.1中进行分区 MySQL5.1中最激动人心的新特性应该就是对水平分区的支持了。这对MySQL的使用者来说确实是个好消息,而且她已经支持分区大部分模式: Range(范围) – 这种模式允许DBA将数据划分不同范围。例如DBA可以将一个表通过年份划分成三个分区,80年代(1980’s)的数据,90年代(1990’s)的数据以及任何在2000年(包括2000年)后的数据。 Hash(哈希) – 这中模式允许DBA通过对表的一个或多个列的Hash Key进行计算,最后通过这个Hash码不同数值对应的数据区域进行分区,。例如DBA可以建立一个对表主键进行分区的表。 Key(键值) – 上面Hash模式的一种延伸,这里的Hash Key是MySQL系统产生的。 List(预定义列表) – 这种模式允许系统通过DBA定义的列表的值所对应的行数据进行分割。例如:DBA建立了一个横跨三个分区的表,分别根据2004年2005年和2006年值所对应的数据。 Composite(复合模式) – 很神秘吧,哈哈,其实是以上模式的组合使用而已,就不解释了。举例:在初始化已经进行了Range范围分区的表上,我们可以对其中一个分区再进行hash哈希分区。 分区带来的好处太多太多了,有多少?俺也不知道,自己猜去吧,要是觉得没有多少就别用,反正俺也不求你用。不过在这里俺强调两点好处: 性能的提升(Increased performance) – 在扫描操作中,如果MySQL的优化器知道哪个分区中才包含特定查询中需要的数据,它就能直接去扫描那些分区的数据,而不用浪费很多时间扫描不需要的地方了。需要举个例子?好啊,百万行的表划分为10个分区,每个分区就包含十万行数据,那么查询分区需要的时间仅仅是全表扫描的十分之一了,很明显的对比。同时对十万行的表建立索引的速度也会比百万行的快得多得多。如果你能把这些分区建立在不同的磁盘上,这时候的I/O读写速度就“不堪设想”(没用错词,真的太快了,理论上100倍的速度提升啊,这是多么快的响应速度啊,所以有点不堪设想了)了。 对数据管理的简化(Simplified data management) – 分区技术可以让DBA对数据的管理能力提升。通过优良的分区,DBA可以简化特定数据操作的执行方式。例如:DBA在对某些分区的内容进行删除的同时能保证余下的分区的数据完整性(这是跟对表的数据删除这种大动作做比较的)。 此外分区是由MySQL系统直接管理的,DBA不需要手工的去划分和维护。例如:这个例如没意思,不讲了,如果你是DBA,只要你划分了分区,以后你就不用管了就是了。 站在性能设计的观点上,俺们对以上的内容也是相当感兴趣滴。通过使用分区和对不同的SQL操作的匹配设计,数据库的性能一定能获得巨大提升。下面咱们一起用用这个MySQL 5.1的新功能看看。 下面所有的测试都在Dell Optiplex box with a Pentium 4 3.00GHz processor, 1GB of RAM机器上(炫耀啊……),Fedora Core 4和MySQL 5.1.6 alpha上运行通过。 如何进行实际分区 看看分区的实际效果吧。我们建立几个同样的MyISAM引擎的表,包含日期敏感的数据,但只对其中一个分区。分区的表(表名为part_tab)我们采用Range范围分区模式,通过年份进行分区: mysql> CREATE TABLE part_tab -> ( c1 int default NULL, -> c2 varchar(30) default NULL, -> c3 date default NULL -> -> ) […]
View Details一、概述 相信有很多人经常会问同样的一个问题:当 MySQL 的总记录数超过了100万后,会出现性能的大幅度下降吗?答案是肯定的,但是性能下降>的比率不一而同,要看系统的架构、应用程序、还有>包括索引、服务器硬件等多种因素而定。当有网友问我这个问题的时候,我最常见的回答>就是:分表,可以根据id区间或者时间先后顺序等多 种规则来分表。分表很容易,然而由此所带来的应用程序甚至是架构方面的改动工作却不>容小觑,还包括将来的扩展性等。 在以前,一种解决方案就是使用 MERGE 类型,这是一个非常方便的做饭。架构和程序基本上不用做改动,不过,它的缺点是显见的: 只能在相同结构的 MyISAM 表上使用 无法享受到 MyISAM 的全部功能,例如无法在 MERGE 类型上执行 FULLTEXT 搜索 它需要使用更多的文件描述符 读取索引更慢 这个时候,MySQL 5.1 中新增的分区(Partition)功能的优势也就很明显了: 与单个磁盘或文件系统分区相比,可以存储更多的数据 很容易就能删除不用或者过时的数据 一些查询可以得到极大的优化 涉及到 SUM()/COUNT() 等聚合函数时,可以并行进行 IO吞吐量更大 分区允许可以设置为任意大小的规则,跨文件系统分配单个表的多个部分。实际上,表的不同部分在不同的位置被存储为单独的表。 二、分区的类型 RANGE 分区:基于属于一个给定连续区间的列值,把多行分配给分区。参见18.2.1节,RANGE分区 LIST 分区:类似于按RANGE分区,区别在于LIST分区是基于列值匹配一个离散值集合中的某个值来进行选择。参见18.2.2节,LIST分区 HASH分区:基于用户定义的表达式的返回值来进行选择的分区,该表达式使用将要插入到表中的这些行的列值进行计算。这个函数可以包>含MySQL中有效的、产生非负整数值的任何表达式。参见18.2.3节,HASH分区 KEY 分区:类似于按HASH分区,区别在于KEY分区只支持计算一列或多列,且MySQL服务器提供其自身的哈希函数。必须有一列或多列包含>整数值。 参见18.2.4节,KEY分区 三、分区例子: RANGE 类型 CREATE TABLE users ( uid INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, name VARCHAR(30) NOT NULL DEFAULT ", email VARCHAR(30) NOT NULL DEFAULT " ) PARTITION BY RANGE (uid) ( PARTITION p0 VALUES LESS THAN (3000000) DATA DIRECTORY = '/data0/data' […]
View Details有时候导入SQL文件后,表很多。想看看表的个数时候和服务器上表的个数是否相同。 在mysql中可以用如下命令查看表的个数: SELECT count(TABLE_NAME) FROM information_schema.TABLES WHERE TABLE_SCHEMA=’dbname'; from:http://www.2cto.com/database/201403/287813.html
View Details在老版本的MySQL 3.22中,MySQL的单表限大小为4GB,当时的MySQL的存储引擎还是ISAM存储引擎。但是,当出现MyISAM存储引擎之后,也就是从MySQL 3.23开始,MySQL单表最大限制就已经扩大到了64PB了(官方文档显示)。也就是说,从目前的技术环境来看,MySQL数据库的MyISAM存储 引擎单表大小限制已经不是有MySQL数据库本身来决定,而是由所在主机的OS上面的文件系统来决定了。 而MySQL另外一个最流行的存储引擎之一Innodb存储数据的策略是分为两种的,一种是共享表空间存储方式,还有一种是独享表空间存储方式。 当使用共享表空间存储方式的时候,Innodb的所有数据保存在一个单独的表空间里面,而这个表空间可以由很多个文件组成,一个表可以跨多个文件存在,所 以其大小限制不再是文件大小的限制,而是其自身的限制。从Innodb的官方文档中可以看到,其表空间的最大限制为64TB,也就是说,Innodb的单 表限制基本上也在64TB左右了,当然这个大小是包括这个表的所有索引等其他相关数据。 而当使用独享表空间来存放Innodb的表的时候,每个表的数据以一个单独的文件来存放,这个时候的单表限制,又变成文件系统的大小限制了。 以下是从收集到的一点信息,不一定全部准确: 操作系统 大小限制 win32 w/ FAT/FAT32 2GB/4GB win32 w/ NTFS 2TB(可能更大) Linux 2.2-Intel 32-bit 2GB (LFS: 4GB) Linux 2.4+ 4TB(ext3) Solaris 9/10 16TB NetWare w/NSS filesystem 8TB MacOS X w/ HFS+ 2TB 以下是MySQL文档中的内容: Windows用户请注意:FAT和VFAT (FAT32)不适合MySQL的生产使用。应使用NTFS。 在默认情况下,MySQL创建的MyISAM表允许的最大尺寸为4GB。你可以使用SHOW TABLE STATUS语句或myisamchk -dv tbl_name检查表的最大尺寸。请参见13.5.4节,“SHOW语法”。 如果需要使用大于4GB的MyISAM表(而且你的操作系统支持大文件),可使用允许AVG_ROW_LENGTH和MAX_ROWS选项的CREATE TABLE语句。创建了表后,也可以使用ALTER TABLE更改这些选项,以增加表的最大允许容量。 from:http://www.2cto.com/database/201111/111978.html
View Details如果你是位个人站长,就能理解网站速度的重要性。自从 Google 算法开始使用网页加载时间作为搜索排序参数之后,网站速度对 SEO 的影响非常大。而且,很慢的加载速度会对网站访问者产生消极的影响。如果你的网站加载速度很慢,需要等待一段时间才能加载,那么用户很有可能不会再次访问 这个网站。 所以,为了解决以上说到的问题,我们收集整理了一个最好的免费网站速度测试和分析工具列表。接下来介绍的工具都是免费,而且会提供非常详细的数据报告给用户,帮助用户做些必要的补救措施。希望大家都能在下面的列表中找到对自己有帮助的,使自己的网站访问速度越来越快! 1. Google PageSpeed Insights Google PageSpeed Insights 允许用户分析网站页面的内容,并且会提供加快网站访问速度的建议。 2. GT Matrix GTmetrix 可以帮助用户开发一个快速,高效,能全面改善用户体验的网站。它会为网站性能打分,然后提供可行性的建议来改善已发现的问题。 3. Neustar Free Load Testing & Performance Test neustar 这个工具是个简单快速生成网站性能分析数据的工具。它能忽略掉大小和地理位置来检测和负载测试网站,非常容易得出网站的性能分析,帮助用户加快网站加载速度。 4. Web Page Analyzer Web Page Analyzer 是个非常强大的速度测试工具,提供详细的网站分析数据并且会提供提高网站性能的建议。它提供大量的 web 页面速度报告,global report,外部文件计算,加载时间,网站分析数据和改善建议。 5. Pingdom Pingdom 是个非常杰出的工具,帮助用户生成大量网站的报告(页面大小,浏览器缓存,性能等级等),确定网站的加载时间,而且允许用户跟踪性能的历史记录,能在不同位置进行网站测试。 6. Load Impact Load Impact 允许用户做些 web 应用的负载和性能测试。它不断增加网站流量来测量网站性能。Load Impact 会选择一个全球负载区,测试模拟客户,带宽,接收数据和每秒请求等。越来越多客户变活跃,这个工具会用个漂亮的图表来展示测量的加载时间。 7. WebPage Test 用户可以使用 WebPage Test 来进行简单的测试,又或者是进行高级的测试,比如多步事物处理,视频采集,内容屏蔽等。测试结果会提供丰富的诊断信息,包括资源加载瀑布图表,页面速度优化检测和改善建议等。 8. Octa Gate Site Timer Octa Gate Site Timer 工具允许用户检测每个用户加载一个或多个页面的时间。当页面加载的时候,SiteTimer 存储每个项目加载的数据和用户接收的数据,这些数据会用一个网格来显示。 9. Which Loads Faster Which Loads Faster 是用来测试 web 性能问题的工具,可以在每个用户的浏览器测试。whichloadsfaster 是开源的,使用 HTML 和 JavaScript 编写的测试工具,完全在客户端运行。 10. Yslow YSlow 能分析 web 页面,基于一系列 web 页面高性能规则提供改进网页性能的建议。 11. Show Slow […]
View Details