qileilove

blog已经转移至github,大家请访问 http://qaseven.github.io/

分享几款一键搭建php本地测试环境工具

  很多朋友平时电脑做服务器都是搭建iis服务器,今天我给大家分享几个一键搭建php本地测试工具!,喜欢做网站论坛的朋友为了使自己的站点能够具有独特的个性和良好的用户体验,总会对自己的站点进行一系列的深度调整,方能充分体现网站特色和唯一性,一般的PHP 本地测试环境【PHP 本地测试、本地服务器、网站制作必备工具】

  Wordpress 够流行了吧,它是一个用 PHP 编写的强大的博客平台。使用它来架设一个博客平 台相关容易,是新手建站比较方便的工具。但是要真正体会 WordPress(以下简称 WP)强 大,插件是不可少的东西。一般来说,我们不可能想试一个插件就把文件通过 FTP 来上传, 然后去自己的网站里试,那样风险大了点。所以我们需要在本地计算机上搭建一个 PHP 平 台。我就把常用的 PHP 本地测试平台都收集一下,给需要的人提供方便。 一般来说,本地的 PHP 平台分为两种,一种是 LAMP,即为 Linux+Apache+MySql+PHP;另一 种是 WAMP,它是 Windows+Apache+MySql+PHP,而前者一般优秀于后者。如果让我们自己来 安装 Apache+MySql+PHP,难度不少,改一堆代码不说,还容易出错。再者考虑到现在大家 大多使用的是 Windows 操作系统,自己又是个 Linux 盲,所以我提供的这些本地测试平台 都是 WAMP,都是集成以上功能的,安装完成即可使用。先大概了解一下吧:

  1、XAMPP

  XAMPP 是一款比较强大的本地测试平台,它集成了必须的三个功能,还带有 FileZilla,软 件带有一个控制面板,在里面可以把 Apache、MySql 和 FileZilla 三者注册为系统服务或 者卸载服务,有服务启动的控制按钮,而且在窗口下部还能看到服务的运行信息。虽说面 板是英文的,但清楚易懂。注册为系统服务有个好处就是开机能够自动运行,但是会消耗 一定的系统资源,怎么取舍用户自己来定。安装成功,服务也启动成功后,就可以把浏览 器打开输入 http://localhost/,试试是否成功。在 XAMPP 的网页选项里,有中文支持。

  2、WampServer

  它的官方网站没有中文,但是程序支持中文。启动安装程序后,它会提示你请先卸载旧版, 不支持覆盖式的升级,然后一路 NEXT 就能安装成功。它在任务托盘里有个图标,如果服务 启动异常,它就是红色的;如果部分异常,它就变成黄色;如果是一切正常,那么它就变 成了白色。这些不同的颜色警示,你很容易判断当前你的 localhost 能不能打开。它还能 切换在线和离线状态,选项中的文语言项中也有简体中文可选,很不错。

  WampServer 2.0c [05/05/2008] Includes : – Apache 2.2.8 – MySQL 5.0.51b – PHP 5.2.6 changelog Downloads http://internap.dl.sourceforge.n … /WampServer2.0c.exe

  3、Vertrigo Server

  这是一个轻量级的 WAMP 环境,但是你下载它的时候,迅雷自带的安全组件居然说它带有病 毒。经过我 的扫描(ESS3.0)和使用来看,这完全是个误报,所以大家可以放心使用。安 装一路 NEXT 就行,其中 PhpMyAdmin 中居然还有原始密码,是 vertrigo,感觉在本地测试 的话,这种默认没有必要。它带有一个简单的控制面板,运行状态也一目了然。 在它的 localhost 页面中带有常用链接,很方便。

  4、PHPNow

  PHPNow 真的很简单,简单到安装程序就是用 RAR 做的一个自解压程序。自释放后快捷方式 也没有,你必须自己找到那个文件存放的文件夹,然后运行 Init.cmd 这个程序来初始化。 初始化过程中提示设置密码,因为是在 CMD 命令行中,只设计了一次密码输入,没有密码 确认项,所以请设置的时候千万小心,不要忘了。它也把式 Apache 和 MySql 注册为服务, 开机自启动。 在程序文件夹中,它也带有控制面板,只不过是 CMD 的,但很好用。 卸载就更容易了,在软件自带的控制面板中卸载服务,然后关把整个文件夹删掉就行。这 么方便,图简便的可以试试。

  5、PHPStudy 本人推荐使用此款

  PHPStudy 不一样,它含有 IIS+PHP 和 Apache+PHP,软件推荐设置是后者。在任务托盘里也有图标,可以打开面板来看服务运行状态,也很简洁。打开 localhost,出现的是标准的 PHP 信息界面。

  6、AppServ

  程序安装过程中它提示你可以改变默认的 80 端口为服务端口,这样可以避免端口共享产生 的冲突。可有密码设置提示,但是做得比 PHPNow 好多了,软件还可以设置字符集,默认为 UTF-8。虽然软件没有控制面板,但一切操作都在开始菜单中加入了快捷方式,使用当然很方便。软件还带有 MySql 命令行终端。 7. EasyPHP 软件如其名,真的很 EASY!安装一路 NEXT,但是不会把 Apache 和 MySql 加载为服务,所 以每次使用都要手工来启动。软件也带简单的控制面板,其他的没什么要说的了。

  说了这么多,我想,这些工具应该够你使用的了,找一个你最满意的安装就行了。 PS:如果某些这样的 PHP 相关的服务无法启动,请注意一下你的机器中的 80 端口是否被占 用。一般的程序,如迅雷,BT 软件什么的,即使它们没有在工作,开着也会占用 80 端口。 所以把它们关掉后,启动 PHP 相关的服务后再把这些下载软件什么的打开,就不会有服务 启动不成功这样的问题的。

posted @ 2012-07-09 10:21 顺其自然EVO 阅读(625) | 评论 (0)编辑 收藏

走进单元测试:测试需要从哪些方面着手

  前言

  笼统的来说测试条件无非就是两个方面:① 正向测试,② 反向测试!

  如果单从这两个方面来思考,肯定出现丢三落四的情况,也就是说不全面,所以应该在上面两种情况的基础上再进行具体划分,那么只要我们能够遵循这些条件基本上就能做到全面(如果能做到,大约80%的问题应该都解决了),于是就出现了下面要说的六个方面内容!

  前辈们把这些测试条件总结为:Right – BICEP

  1、Right - 做正确的事,可以说是“正向测试”

  这种测试前期任务是要准备足够的正确数据(前提是要保证数据的正确性,这个很重要),运行代码后返回的值或产生的影响是要跟自己的预期是一致的!

  注意:如果准备的数据太大或容易丢失,建议把它放在数据文件中,然后让单元测试读取这个文件,这种方法会在下一篇会说到!

  2、B - 边界条件(Boundary)

  边界条件是测试里面的重中之重,必须要有足够的认识和重视!

  而它又被分为七个方面的子条件,下面就让我们来一一熟悉它!

  ① 一致性(Conformance)

  数据是否符合我规定的格式(也可以说是非法字符吧)!

  案例:比如我传入的参数文件名需要的格式是:文件名 + 日期(yy-mm-dd) + 扩展名,那么我就要写一个测试传入的文件名为 :“sa#$#$#$#”这样的格式!

  ② 有序性(Ordering)

  这方面主要是对涉及到数组和集合的数据,而且对数据的顺序有严格要求的函数,需要对它们里面数据的顺序进行测试!

  比如:点菜系统菜谱中每道菜的顺序,或者去银行办理业务的排队系统等等!

  ③ 范围,区间性(Range)

  值是否存在于一个最大值和一个最小值之间,主要是对值类型的数据做的测试!

  这里面还有一个重要的测试点是 → 对数组,集合,以及Table,DataSet中的索引值进行测试,比如索引值不能为负,不能超出索引的范围等等情况!

  比如:一个通过ID来搜索信息的函数,应该对这个ID进行最大值和最小值的测试!

  ④ 引用,耦合性(Reference)

  这方面主要是:代码是否引用了一些不受本身代码控制的外部因素(比如:调用第三方接口,调用其它模块的接口等等)!

  对于这些情况我们是没有办法控制的,所以在测试的时候只能模拟,而在模拟时我们会用到“Mole”技术,让它来帮助我们创建一个模拟环境(下一篇会介绍)!

  比如:有的项目会调用银行接口,这种情况下只能先创造一个虚拟银行接口,然后再进行测试!

  ⑤ 存在性(Exist)

  固定的测试,如Null,Empty,非零等等,这些都是必须考虑的!

  ⑥ 基数性(Cardinality)

  对于这个测试说起来还是蛮难理解,这个测试只有在特定的场合下才会去考虑它!

  它遵循一个原则:“0-1-N”!

  ⑦ 时间性(Timer)

  对时间比较有依赖的软件或系统应该在这个方面着重测试!

  主要考虑:事情是否按时间的顺序执行,是否在正确的时间执行,是否出现执行事情延误了!

  相对时间:网站超时,数据更新超时等等!

  绝对时间:不同的client间的时间是否同步!

  并发问题在时间性测试中比较重要!

  3、I - 反向关联(Inversion)

  在准备数据或者验证数据时的一种反向思维,涉及到个人的思维方式问题了!

  比如:有个函数对数据库进行了操作,但是它没任何返回值也没有任何提示,如果你是对正确的数据进行了测试,那么你要怎么知道测试结果跟你的预期一致呢,这里你就应该去查找数据库,看数据库里面的数据是否有真的改动,这就是一种反向的思维方式!

  4、C - 交叉检查(Cross)

  用一种数量检查另一种数量(需要考虑的情况不是很多)!

  5、E - 强制产生错误(Error)

  通过代码强制产生软件在运行过程中出现的特殊情况!

  可以参考下面几种测试方面:内存耗光,磁盘用满,断电,正在执行更新数据时出现断网现象,网络负载严重导致瘫痪,系统时间出现导致和国际时间不一致等等一些情况!

  6、P - 性能特性(Property)

  性能测试工具的使用,没具体研究过性能测试工具,知道的朋友可以说下你们的经验!

  进行压力测试,一点一点的加大数据量,10000条,100000条,1000000条这样进行压力测试!

  总结:本人对反向关联和交叉检查这两个测试条件不是很理解,知道的朋友可以留言给我,我会把它补充到文章中去!

  最后:下面是我对测试条件的小小总结,比较简陋!

posted @ 2012-07-09 10:19 顺其自然EVO 阅读(300) | 评论 (0)编辑 收藏

性能测试知多少---并发用户

性能测试知多少---并发用户

  在做性能测试的时候,我们常常听到并发用户、响应时间、吞吐量专业术语,也许大家都理解,这里有一个理解的层次与深度概念。最近有看断念《软件性能详解与案例分析》一书,看了他的讲解,原来我对这些术语的理解还是比较肤浅,其实,这里也主要受制于自己的知识面。所以,再拿出来与大家重温一下。

  ps:按照惯例先上个图,因为看纯文字的文章比较累!^_^

  并发用户数

  大家都知道我们的性能测试就通过工具模拟多用户对系统进行操作,对系统造成压力,来验证系统的性能(不太标准的解释)。好多人也简单的把性能测试当成并发测试。那么这个“多用户”和“同时”两个因素缺一不可。只多用户不同时,很难对系统构成压力;没有多个用户,同时的概念也就自然不存在了

  并发的两种情况

  一种是严格意义上的并发,即所有的用户在同一时刻做同一件事或操作,这种操作一般指做同一类型的业务。比如,所有用户同一时刻做并发登陆,同一时刻做表单提交。

  另外一种并发是广义范围的并发,这种并发与前一种并发的区别是,尽管多个用户对系统发出了请求或者进行了操作,但是这些请求或都操作可以是相同的,也可以是不同的。比如,在同一时刻有用户在登录,有用户在提交表单。

  从服务器的角度来看并发

  前面的两种解释都是从用户业务的角度来解释并发的,因为我们平时所做的性能测试也是从用户端对业务层的操作来进行并发测试的。

  如果考虑整个系统运行过程中服务器所承受的压力是这样的:在该系统的运行过程中,把整个运行过程划分为离散的时间点,在每个点上,都有一个“同时向服务端发送请求的客户数”,这个就是所谓的服务器所承受的最大并发访问数。

  真正意义上的并发不存在

  上面试谈了这么多并发,现在又说真正意义上的并发不存在。何解?学操作系统原理的同学都知道,CPU在一个时间点上只能干一件事儿。为什么我们可以边看电影,边打字,边语音。因为CPU很快很快,他可以处理一下电影,再处理一下打字,再处理一下语音。因为它很快,所以,它可以在多个程序之间快速瞬间的切换,给你造成的假象就是它在同时做这些事情。(现在的双核、四核的CPU另说)

  那么我们的系统在接到用户的请求后也要调用CPU来完成某些处理,然后返回给用户。那么我们对系统有做并发测试是测什么呢?举个简单的例子。假如有一位神医,他的看病速度非常快,假设他的看病速度是不变的;然后有一群接待人员来接待看病的客人,有成千上万的病人来看病,接待人员要想各种办法来做好接待工作,使病人更快的看到病。比如,可以事先咨询病人得的什么病,然后将病人进行分类,比如可以扩大接待室,让更多的病人可以进到医院来看病等。

  神医就是我们的CPU,接待人员就是我们的系统,病人就用户,我们做性能测试的目的就是了解接待人员哪个地方给医院看病造成了瓶颈。只来一个病人,医院的看病速度与服务很好。一下子来十万个病人各种问题就出来了。接待人员的服务态度下降,多余的人员跟本进不到医院去,医院的洗手间不够用,造成病人无法上则所而离开,这些都属于系统问题。所以,我们一般测试的目的是看医院的接待能力。

  系统用户数与同时在线人数

  在实际的性能测试中,经常接触到与并发用户相关的概念还有“系统用户数”与“同时在线人数”下面通过一个实例来描述他们之间的差别。

  假设有一个网站,注册用户才能登录使用各种功能,如上传头像,阅读专家文章等。该系统有20万注册用户,这就是说有20万用户可以使用这个网站的所有功能,20万就是这个网站的“系统用户数”,网站有一个在线统计功能,从统计数据中可以看到,同时登录网站的人数的最高记录是2万,就是有2万人同时用浏览器打开着这个网站。2万就是“同时在线人数”

  那么系统的并发用户数是多少呢?2万么?NO!这2万只表示在系统最高峰时有这么多用户登录了网站,并不表示实际服务器的承受压力。因为服务器承受压力还与具体的用户访问模式相关,在这2万用户中考察某一个时间点对用户发出请求数,可以会大大缩水。那么,该系统的服务端承受的最大并发访问数是多少呢?这个取决于业务并发用户数和业务场景,一般可以通过服务器日志的分析得到。

  求并发用户数公式

  在实际的性能测试工作中,测试人员一般比较关心的是业务并发用户数,也就是从业务的角度关注应该设置多少个并发数比较合理。

  下面找一个典型的上班签到系统,早上8点上班,7点半到8点的30分钟的时间里用户会登录签到系统进行签到。公司员工为1000人,平均每个员上登录签到系统的时长为5分钟。可以用下面的方法计算。

  C=1000*5/30=166.7

  C表示平均并发用户数,那么对这个签到系统每秒的平均并发用户数为166

  当然,在性能测试上,任何公式都不是严谨的,最重要的是对系统做出有效正确的分析。

posted @ 2012-07-09 10:15 顺其自然EVO 阅读(442) | 评论 (0)编辑 收藏

内功修炼之操作系统学习(存储管理)

  存储器管理负责管理计算机系统中重要的资源---主存储器。任何程序和数据必须载入到主存中才得以执行和处理,因此存储器管理的优劣直接影响系统的性能。

  主存分为两部分:一部分是系统区,用于存放操作系统内核程序和数据结构等。另一部分是用户区,用于存放应用程序和数据。

  计算机系统采用层次结构的存储系统。以便在容量大小、速度快慢、价格高低等诸多因素中取得平衡。它分为五个层次:寄存器,高速缓存,主存储器,磁盘,磁带等五层。寄存器,高速缓存和主存储器属于操作系统存储管理管辖范畴。磁盘和磁带属于设备管理的管辖对象。

  由于程序在执行和处理数据时往往存在顺序性和局部性,因此在执行时并不需要将其全部调入主存,而仅调用当前使用的一部分,其他部分待需要时再逐步调入。基于这个原理操作系统可以向用户提供比实际主存大得多的存储空间,可以设计出多级层次式体系结构的存储子系统。

  源程序经过编译,链接,装入三个阶段后才能装入主存执行。一个程序可由独立编写且具有不同功能的多个源程序模块组成。由于模块包含外部引用:指向其他模块中的数据或函数的地址或包含对库函数的引用。编译程序负责记录引用的发生位置,编译或汇编的结果将产生相应的多个目标模块,每个模块都附有供引用使用的内部符号表和外部符号表。符号表中依次给出个符号名及在本目标模块中的名字地址,在模块被链接时进行转换。

  链接程序的作用是把多个目标模块链接成一个完整的可重定位程序,这需要解析内部和外部符号表,把对符号的引用转换为数值引用,将对符号引用的程序入口点和数据引用点转换为数值地址。Linker首先将主程序调入工作区,然后扫描外部符号表,获得外部符号。用取得的符号名从标准函数库或其他库中找出此符号对应的.o文件,装入工作区并拼接到主程序之后作为程序的一部分。

  磁盘中存储的代码模块使用的是逻辑地址。逻辑地址空间可以是一维的,从0开始线形排列。也可以是二维的,此时整个程序被分为多个段,每段都有不同的段号,段内地址从0开始编址。

  进程运行时,数据和代码模块被装入物理地址空间,程序和数据的实际地址通常不可能同原来的逻辑地址一致。把逻辑地址转换为物理地址的过程称为地址重定位(与基址重定位相区别)。有两种方式:

  1:静态地址重定位:由载入程序实现地址转换,将所有的逻辑地址修改成主存物理地址。地址转换工作在进程执行前一次完成,无须硬件支持,易于实现,但是不允许程序在进程中移动位置。早期的计算机系统使用此方法。

  2:动态地址重定位:加载程序将程序的数据和代码加载到指定的主存区域后,并不对链接器处理过的应用程序的逻辑地址进行修改,但程序在主存的起始地址被置入硬件专用寄存器---重定位寄存器。程序执行过程中,每当cpu访问数据和代码时,由硬件截取此逻辑地址,并在它被发送到主存储器之前加上重定位寄存器的值以便实现地址转换。这被称为动态重定位,地址转换被推迟到最后的可能时刻--执行时才完成。这允许程序在主存中移动,便于程序共享且主存利用率高。

  为了支持动态重定位cpu至少要有三个重定位寄存器。将代码段、数据段和堆栈段分别作为三个可重定位的模块。Intel x86有6个重定位寄存器。

  要将动态地址重定位与根据重定位段进行的基址重定位区分开来。基址重定位是当exe或dll没有加载到其首选基址时,所有涉及对逻辑地址引用的代码都需要修改成相对于exe或dll实际载入的逻辑地址条件下的偏移地址。它是对逻辑地址进行操作。而当exe或dll被加载到首选基地址时,基址重定位不会发生。但是任何程序都会进行动态地址重定位,将逻辑地址转换为物理地址。

  在多道程序设计中,可用的主存通常被多个进程共享,必须允许进程所使用的内存因对换或空闲区收集而被移动,这需要动态地址重定位支持。无论采取何种重定位方式,通常进程运行时会对需要访问所有主存地址进行检查,确保进程仅访问自己的存储区。这就是地址越界保护,它依赖于硬件。除了地址越界保护之外,还要进行访问权限检查,如允许读、写、执行等,从而保证数据的安全性和完整性,这就是信息存取保护。

  固定分区存储管理的基本思想:主存空间被划分成数目固定不变的分区,各个分区大小不等,每个分区只装入一个作业,若多个分区都装有作业则它们可以并发执行。缺点:预先规定分区大小使得大作业无法装入。作业很少会恰好填满分区,主存利用率不高。

  可变分区管理又称为动态分区管理,按照作业大小来划分分区,但划分的时间、大小、位置都是动态的。系统把作业装入主存时,根据其所需要的主存容量查看是否有足够的空间。若有,则按需分配一个分区给此作业;若无,则令此作业等待主存资源 。由于分区大小是按需求而定的,因此分区数目是可变的。这可以提高主存利用率。

  用于管理的数据结构由两张表组成:已分配分区表和未分配区表。当装入新作业时,从未分配表中找出一个足够容纳它的空闲区。将此区分成两部分,一部分用来装入作业,另一部分仍是空闲区。然后在已分配的表中登记新作业的起始地址、占用长度,同时修改未分配区表中空闲区的长度和起始地址。当作业撤离时,已分配区表中的相应状态变为空,而将收回的分区登记到未分配区表中,若有相邻空闲区,将其合并后登记。

  已分配分区表和未分配分区表采用链表是不错的选择。在内部各分区都可按一定的规则排列。如按空闲区大小、地址排列。

  常用的可变分区分配算法有以下五种:

  1:最先适应分配算法:顺序查找未分配表找出一个满足需要的。

  2:下次适应分配算法:总是从未分配区的上次扫描结束处顺序查找未分配区表。

  3:最优适应分配算法:扫描整个未分配区表,从中找出一个能满足需要的最小分区进行分配。查找前分区一般按大小排列。

  4:最坏适应分配算法:扫描整个未分配分区表,总是挑选一个最大的空闲区分割给作业使用。

  5:快速适应分配算法:为那些经常使用的长度设立单独的空闲区链表。

 对可变分区需采用动态地址重定位,进程的程序和数据的地址转换由硬件完成,硬件设置两个专用控制寄存器:基址寄存器和限长寄存器。基址寄存器存放分配给进程使用的分区的起始地址,限长寄存器存放进程所占用的连续存储空间的长度。当进程占有cpu运行后,操作系统可把分区的起始地址和长度送入基址寄存器和限长寄存器,在执行指令或访问数据时,由硬件根据基址寄存器进行地址转换得到绝对地址。

  当逻辑地址小于限长值时,逻辑地址加上基址寄存器的值就可以获得绝对地址。当逻辑地址大于限长值时表示进程所访问的地址超过所分得的区域,此时不允许访问。

  C语言的程序会被编译成至少三个段:代码段,数据段,堆栈段。Intel x86平台提供专用的存放段基址的寄存器:代码段寄存器CS在指令执行期间重定位指令地址;堆栈段寄存器SS为栈指令执行重定位地址;数据段寄存器DS在指令执行周期内重定位其他地址。提供多对基址、限长寄存器的机器中,允许一个进程占用两个或多个分区。可规定某对基址、限长寄存器的区域是共享的,用来存放共享的程序和数据。

  可变分区中常常出现分散的小空闲区,称之为碎片。当在分区表中找不到足够大的空闲区来装入进程时,可采用移动技术把已在主存中的进程分区连接到一起,使分散的空闲区汇集成片。这就是移动技术。第一种方法是把所有当前占用的分区移动到主存一端。第二种是也是把占用分区移动到另一端,但是当产生足够大的空闲区就停止移动。

  分区方式管理存储器,每道程序要求占用主存的一个或多个连续存储区域,这样不仅导致主存中产生碎片,而且处理器的开销太大。分页存储管理允许程序存放到若干不相邻的空闲块中,既可以免除移动信息工作也可充分利用主存空间。

  进程逻辑地址空间分成大小相等的区,每个分区成为页面或页,页号从0开始依次编号。 把主存物理地址空间分成大小相等的区,每个区是一个物理块或页框。页框大小与页面大小相等。

  与此对应分页存储器的逻辑地址由两部分组成:页号和页内位移。逻辑地址是连续的,用户在编制程序时仍使用相对地址,不必考虑如何分页,由硬件地址转换机构和操作系统的管理需要来决定页面尺寸,从而确定主存的分块大小。进程在主存中的每个页框内的地址是连续的,但页框之间的地址可以不连续。

  页表用于是操作系统为进程建立的,是程序页面和主存对应页框的对照表。页表中的每一栏指明程序中的一个页面和分得页框之间的对应关系。从数学角度来看,页表表示一个函数,其变量是页面号,函数值为页框号,通过页表可以把逻辑地址中的逻辑页面替换成物理页框。进程页表存放在内存中,系统设置了专门的硬件:页表基址寄存器(一对,地址和长度),存放当前运行进程页表的起始地址 ,以加快地址转换速度。

  进程运行前由系统把它的页表基地址送入页表基址寄存器,运行时借助于硬件的地址转换,按页面动态地址重定位。当cpu获得逻辑地址后,由硬件按设定的页面尺寸分成两部分:页号和页内位移。先从页表基地址寄存器找到页表基地址,再用页号作为索引查找页表,得到对应的页框号。根据

  物理地址=页框号*块长+页内位移。

  计算出欲访问的主存单元。虽然进程存放在若干不连续的页框中,

  但在执行过程中总能按正确的物理地址进行存取。

  按照给定逻辑地址进行读写操作时,至少访问两次主存:一次访问页面,另一个根据物理地址访问指令或数据。为了提高运算速度,设置了专门的硬件,用来存放进程最近访问的部分页表项,被称为转换后援缓冲或快表。对快表的访问速度远快于主存,但造价高,且只能存储几十个页表项。块表项包含页号及对应的页框号,它通过并行匹配对所有快表项进行查找。如果找不到,再查主存中的页表,同时将页号即页框号登记到快表中。当块表快满时,需要淘汰旧的块表项,最简单的策略是先进先出。

  通过快表实现主存访问的比率成为命中率。快表与高速缓存不同,前者记录最近转换的页号即页框号,后者保存最近实际访问的指令或数据的副本。

  分页存储管理能实现多个进程共享程序和数据,共享页面信息可大大提高主存空间的利用率。实现页面共享必须区分数据共享和程序共享。实现数据共享时,允许不同进程对共享的数据页面用不同的页号,只要让各自页表中的有关表项指向共享的数据页框。实现程序共享时,由于指令包含指向其他指令或数据的地址,进程依赖于这些地址才能执行,所以,不同进程正确执行共享代码页面,必须为它们在所有逻辑地址空间中指定同样的页号。实现信息共享必须解决共享信息的保护问题,通常的做法是在页表中增加标志位,指出此页的访问模式。进程访问时核对访问模式,当模式不符时抛出异常。

  分页存储管理是实存管理,必须为进程分配足够的主存空间,装入其全部信息,否则进程无法运行。把进程的全部信息装入主存后,实际上并非同时使用,有些部分甚至从不使用,这是对主存资源的一种浪费。于是提出一种想法:不必装入进程的全部信息,仅将当前使用部分先装入主存,其余部分存放在磁盘中,待使用时由系统自动将其装进来,这就是虚拟存储管理技术的基本思路。

  当进程被创建时,代码段和数据段部分数据被调入内存。如果处理器访问的程序或数据不在内存,系统自动将这部分信息从磁盘装入,这叫做部分装入。若此时内存没有足够的空闲空间,便把主存中暂时不用的信息移至磁盘,这叫做部分替换。在具有层次存储结构的计算机系统中,自动实现部分装入和部分替换功能,能从逻辑上为用户提供一个比实际物理存储器大得多的、可寻址的“主存储器”,这被称为虚拟存储器。它对用户隐蔽内部细节。虚拟地址空间等同于实际物理主存加部分硬盘区域的存储空间。引用基础是:程序执行的局部性原理:某存储单元被使用后,其相邻的存储单元也很快被使用---空间局部性。最近访问过的程序代码和数据很快被访问---时间局部性。

  虚拟存储器是基于程序局部性原理的一种假想的而非物理存在的存储器,其主要任务是:基于程序局部性特点,当进程使用某部分地址空间时,保证将相应部分加载至主存中。这种将物理空间和逻辑空间分开编制、互相隔离,但又统一管理和使用的计数为用户编程提供了极大地方便。

虚拟存储管理与对换有很大区别。兑换技术以进程为单位,当所需的主存空间大于当前系统的拥有量时,进程无法对换进主存工作。而虚拟存储管理以页或段为单位,即使进程所需主存空间大于当前系统拥有的主存总量,仍然能够正常运行。

  操作系统的存储管理依靠底层硬件MMU(主存管理部件)来完成,它提供地址转换和存储保护的功能。

  每当进程上下文发生切换时,系统负责把要运行的进程的页表基地址装入页表寄存器,此页表便成为活动页表。MMU只对页表基址寄存器所指出的活动页表进行操作。然后将逻辑地址分解为页面号和页内位移,以便进行地址转换。对快表的管理设计两个方面:一是直接查找快表,找到相应的页框后去拼接物理地址。二是装入表目和清除表目,每次发生快表查找不命中的情况后,待缺页中断处理结束,把相应的页面和页框号装入。

  请求分页虚拟存储管理是将进程信息的副本存放在辅助存储器中,当它被调度投入运行时,并不把程序和数据全部装入主存,仅装入当前使用的页面,访问到不在主存的页面时再动态的把所需的信息装入。请求分页:当需要执行某条指令或使用某个数据而发现它们不在主存时,产生缺页中断,系统从磁盘把此指令或数据所在的页面装入。

  请求分页虚拟存储管理属于虚拟存储,与分页实存管理不同,仅让当前使用部分装入,必然会发生某些页面不在主存的情况,为了标记页面是否在主存中,所采用的方法为:扩充页表项的内容,增加驻留标志位,又称页失效异常位,用来指处页面是否装入主存。当访问一个页面时,如果某页的驻留标识为1,表示此页已经在主存中,可被正常访问。如果某页的驻留标识为0,不能立即访问,产生缺页中断,操作系统根据磁盘地址将这个页面调入主存,然后重新启动相应指令。

  页面装入策略决定何时把页面装入主存,有两种策略:

  1:请页式,仅当需要访问程序和数据时,通过缺页中断并由缺页中断处理程序分配页框,把所需页面装入主存。

  2:预调式,装入主存的页面并非缺页中断请求的页面,是由操作系统依据某种算法,动态预测进程最可能要访问的那些页面。

  页面清除策略与装入策略相对应,要考虑何时把修改过的页面写回辅助存储器,常用的算法是:

  1:请页式清除,仅当一页被选中进行替换且被修改过,才把它写回磁盘。

  2:预约式清除,对于所有更改过的页面,在需要替换之前把它们都写回磁盘。

  在多道程序设计中,属于不同进程的页面被分散存放在主存页框中,当发生缺页中断时,如果已无空闲页框,系统要选择一个驻留页面进行淘汰。

  页面替换有两种策略:

  1:局部替换,页面替换算法局限于进程自身。

  2:全局替换,页面替换算法的作用范围是整个系统。

  全局替换算法有以下几种算法:

  1:最佳页面替换算法(optimal replacement ,OPT):当要调入一页而必须淘汰旧页时,应该淘汰以后不再访问的页,或距现在最长时间后要访问的页。它所产生的缺页数最少。这只是一种理想的情况。

  2:先进先出页面替换算法(FIFO)

  基于程序总是按线形顺序来访问物理空间这一假设,总是淘汰最先调入主存的页面,即淘汰在主存中驻留时间最长的页面。

  3:最近最少使用页面替换算法(Least Recently Used ,LRU)

  淘汰的页面是在最近一段时间内最久未被访问的那一页。

  4:第二次机会页面替换(Second Chance Replacement ,SCR)

  此算法是将FIFO算法与页表中的引用位结合起来使用,实现思想:首先检查FIFO页面队列中的队首,这是最早进入主存的页面,如果其引用位是0,那么这个页面不仅入队时间长,而且没有使用。如果引用位为1,说明它进入主存的时间较早,但最近仍在使用,于是将其引用位归0,置于队尾,把它看成新调入的页,再给一次机会。

  5:时钟页面替换算法(Clock policy replacement)

相关链接:

内功修炼之操作系统学习(处理器管理)

内功修炼之操作系统学习(同步、通信及死锁)

posted @ 2012-07-09 10:09 顺其自然EVO 阅读(468) | 评论 (0)编辑 收藏

SQL Server查询性能优化之创建合理的索引(下)

  续上一篇SQLServer查询性能优化之创建合理的索引(上)

  数据库索引分为聚集索引和非聚集索引,聚集索引就是物理索引,也就是数据的物理的存储顺序,聚集索引的叶子节点就是数据行本身;非聚集索引是逻辑索引,也可以简单的认为是对聚集索引建立的索引,一般来说聚集索引的键就是非聚集索引的叶子节点(在不使用include时)。

  关于索引的选择

  对于索引类型来说没什么好选的,一般来说聚集索引是必须的(有特殊需要的另说),非聚集索引看实际需要灵活建立。因此对于索引来说主要是决定在那些列上建立索引,尤其是对于聚集索引这点非常重要。

  聚集索引

  聚集索引作为最重要的索引往往被我们所忽略,而其最大的优势就是大范围数据查询有着较高的效率,因此聚集索引列的选择往往对数据库性能有着灰常大的影响。为了尽量发挥聚集索引在大范围数据查找上的优势,推荐按以下顺序选择聚集索引列。

  聚集索引字段选择优先级:时间字段>>会进行大范围查询的列>>具有唯一值的有实际意义的字段>>自增列ID

  1、时间字段:若表里面有时间列,并且时间是按照数据插入顺序增长时(时间无需唯一即可有重复值,哪怕是大范围重复),建议采用时间列作为聚集索引的第一选择。理由:聚集索引有一个巨大的优势就是进行大范围数据查找,而且这个优势会随着数据量的增加而越来越明显,一般来说我们需要进行大数据量范围查询时都会用时间列围作为筛选条件,由于聚集索引不存在书签查找而且可以进行连续扫描,因此查询速度会非常快。时间列数据最好是顺序插入的这样可以尽量减少磁盘碎片,是数据存储相对集中,便于连续数据读取。

  2、会进行大范围查询的列:若表里面没有时间字段或者时间字段不适合做聚集索引,可以选择那些在建表时就明确知道会经常进行大范围数据筛选的列,而且最好是选择性较低的列(即有较多重复值的列,性别这种列不算啦),如有必要可以使用组合索引。理由:聚集索引在数据查询的优势主要在于范围数据查找,把聚集索引弄成唯一的把这个大好优势给白白浪费了。

  3、具有唯一值的有实际意义的字段:若找不到适合条件1、2的列,那还是乖乖的把聚集索引列建立在唯一列上吧,最好找那种有实际意义的具有唯一性的列,比如订单表可以用订单号作聚集索引,订单明细表使用订单号和产品编号做联合聚集索引。理由:找不到合适的时间字段和较低选择性字段的话,把主键建成聚集索引是我们大多情况下的选择。

  这里建议把唯一性的聚集索引顺便建成主键,和编码时方法、变量命名一样,推荐列名自解释,即看到列名就知道它就是主键,省得你再去猜,比如订单表你来个自增ID列做主键,再建一个OrderCode列做订单号,用这个表时你得怀疑这个OrderCode是不是唯一滴呢,有木有建立唯一约束呢,同理在订单明细表来个自增列ID也会产生如此疑问,产生疑问还是小事,若是你忘记了在应该唯一的列上建立约束,没准哪天程序控制不好给你个巨大的惊喜。

  4、自增列ID:前面3中条件都找不到合适的列了还是使用我们的神器自增列ID吧,自增列ID也是我们使用最多的主键(顺便也就成聚集索引了),而且能较好满足我们大多数需求。自增ID列堪称无所不能,int类型只占用4个字节完全满足窄索引要求,绝对的顺序存储可以有效降低索引碎片,完全符合我们的见表习惯,有用没用来个自增ID列做主键总是没错滴。

  这里考虑聚集索引的键列主要为查询考虑,有些观点认为应该总是把聚集索引建立唯一列上,这里不敢苟同,诚然有些特殊情况下确实需要这么做,但大说情况下还是建立在选择性较低的列、时间列上比较好,这样才能发挥聚集索引在范围数据查找方面的巨大优势。关于聚集索引在列上重复数据SQL Server需要额外的建立唯一标示用以定位造成查询时的额外开销非常小,小到与其带来范围查找的优势而言完全可以忽略。

  当然了在选择列时要尽量使用窄索引,也只是尽量而已,主要还是看付出的代价还获得的收益,若有足够的收益啥玩意都可以滴。记住我们滴目标是利用聚集索引提高大范围查询效率。

  非聚集索引

  与聚集索引不同,非聚集索引可以建立多个,这也给我们带来了很大的灵活,毕竟聚集索引就那么一个不可能靠它满足所有需求,更多的我们得依赖非聚集索引。记住非聚集索引不是大白菜,你想键多少就建多少,建立索引是有代价的,任何涉及到索引列的数据修改都会导致索引的修改,索引越多数据的曾、删、改的额外代价也就越大。对于非聚集索引来说,我们的目标是用尽可能少的索引覆盖尽可能多的查询。

  非聚集索引的列选择顺序(组合索引):经常被使用为查询条件列>>具有较高选择性的列(选择性越高越好,唯一最好)>>经常排序的列

  1、经常被使用为查询条件列:我们的查询千变万化,建立索引时要首先考虑有哪些列被经常性的用于各种查询,把使用频率较高的列作为组合索引的第一列(先导列),若一个查询中没有用到组合索引中的先导列,多数情况下这个索引就不会被使用,因此为了尽可能多的复用组合索引把使用较多的查询列作为组合索引的第一列吧。(关于这点对于聚集索引的组合索引同样适用)

  2、具有较高选择性的列:这点很简单尽量使用高选择性列作为先导列,如果可以通过第一个条件过滤(随便什么判定逻辑=、>、<、like),只要能大幅减少数据范围,就把它作为先导列。

  3、条件1、2、3都确定不了时那就用经常被排序的列吧,我们的很多操作都需要先进行排序才可以进行进一步查询,比如group by,like等操作都是要先进行排序操作才可以完成下一步查询。

  补充一点:可以把经常被返回的列放到索引的include里面去,在不增加索引键大小的情况下尽可能覆盖尽可能多的列,这样当遇到某些查询,没有用到组合索引的先导列,但又感觉不值得为其建立索引时,若此查询用到得字段被组合索引实现了索引覆盖,可以进行非聚集索引扫描完成查询(当非聚集索引实现了索引覆盖时,进行非聚集索引扫描有着比聚集索引扫描更好的效率)。

  下面我们用一些示例来简单说明下

CREATE TABLE Orders
(
    ID INT IDENTITY PRIMARY KEY,--自增列ID做主键,这样创建默认就成了聚集索引
    OrderCode BIGINT NOT NULL,--订单号
    Price DECIMAL(18,2) NOT NULL,--订单金额
    UserID INT NOT NULL,--用户ID
    [Status] INT NOT NULL,--订单状态
    PostTime DATETIME NOT NULL,--下单时间
    Moblie CHAR(11) NOT NULL,--用户手机号
    [Address] NVARCHAR(200) NOT NULL--收获地址
)

  创建一个订单表,按照我们的习惯有用没用来个自增列ID做主键,随随便便也就建立了聚集索引,现在我们来看一下,对于订单表来我们一般都会一组规则生成订单号,而不是简单的使用自增ID,因此我们创建了OrderCode用作订单号,当然了订单号必须是唯一的,因此需要创建唯一约束,过了些日子有其它人用到订单表或你自己用这个表,难免就会有些疑惑,OrderCode需要唯一,在这个表里到底是不是唯一的呢,于是乎你首先查看OrderCode上面是否建立了唯一约束,然后知道OrderCode就是唯一的,这也没啥,但是来个人都要查一遍,过段时间忘了还得再确认一次,很是麻烦,再看看我们那个主键ID,他神马都没干,就在那里呆着,现在拿掉它,于是表变为

CREATE TABLE Orders
(
    OrderCode BIGINT NOT NULL PRIMARY KEY,--订单号
    Price DECIMAL(18,2) NOT NULL,--订单金额
    UserID INT NOT NULL,--用户ID
    [Status] INT NOT NULL,--订单状态
    PostTime DATETIME NOT NULL,--下单时间
    Moblie CHAR(11) NOT NULL,--用户手机号
    [Address] NVARCHAR(200) NOT NULL--收获地址
)

  现在不管谁、什么时候看到这个表基本上不会怀疑OrderCode是否唯一了,一个不起眼的小改进,带来了很大的便利,所以主键自解释很有必要的

  我们看一下以下几个可能经常用到的查询

--查询1:指定用户特定时间内的所有订单
SELECT * FROM dbo.Orders WHERE UserID=1 AND PostTime BETWEEN '2012-6-1' AND '2012-6-30'
--查询2:指定用户的单个订单
SELECT * FROM dbo.Orders WHERE UserID=1 AND OrderCode=22222222222
--查询3:指定用户特定时间内特定状态的订单
SELECT * FROM dbo.Orders WHERE UserID=1 AND Status=1 AND PostTime BETWEEN '2012-6-1' AND '2012-6-30'
--查询4:指定时间内所有的订单
SELECT * FROM dbo.Orders WHERE PostTime BETWEEN '2012-6-1' AND '2012-6-30' AND Status=1

  为了最优查询速度有可能会创建以下索引

索引1:
CREATE INDEX IX_UserIDPostTime ON dbo.Orders(UserID,PostTime)
索引2:
CREATE INDEX IX_UserIDOrderCode ON dbo.Orders(UserID,OrderCode)
索引3:
CREATE INDEX IX_UserIDStatusPostTime ON dbo.Orders(UserID, Status,PostTime)
索引4:
CREATE INDEX IX_PostTimeStatus ON dbo.Orders(PostTime,Status)

  最悲观的情况下上面4个索引可能同时存在,为每一个查询建立对应的索引固然可行,但代价未免太大,别忘了索引不是大白菜。因此我们应尽可能的用少的索引覆盖多的查询。来看下上面的索引,如果只创建了索引1,那么只有查询1、3能从索引1受益,查询4没用用到索引1的先导列故不会用到索引1,查询2由于聚集索引存在根本不需要额外的非聚集索引。而索引2由于聚集索引的存在更是完全没必要存在,因此首先干掉索引2。再看索引3,索引3可以覆盖查询1和查询3、查询4,但由于索引列顺序问题使其在应对查询4时基本无效,对查询1虽然有效但效果不尽如人意,我们对索引3做下简单调整,把PostTime列和Status列顺序互换,修改后索引3对原查询3基本没影响,而且对查询1的效率提升也达到最大化

修改后的索引3:
CREATE INDEX IX_UserIDPostTimeStatus ON dbo.Orders(UserID,PostTime,Status)

  现在索引3可以很好的完成查询1和查询3,因此索引1现在可以删除掉,现在只剩索引3和索引4了,我们可以看到修改后的索引3由于先导列问题依然无法用于查询4,为了使索引3用于查询4我们再次修改索引3,把PostTime放到索引的第一列,其它列保持顺序不变

再次修改后的索引3:
CREATE INDEX IX_PostTimeUserIDStatus ON dbo.Orders(PostTime,UserID,Status)

可以看到现在索引3也可以有效的用于查询4了,但是由于先导列原因若将Status列和UserID列换货,固然可以提高查询4效率但是会影响查询1,我们考虑到Status列一般也就几种状态,多了也就几十种,相对于UserID来说选择性低高,因此还是把选择性较高的UserID列放在前面,最大化查询1和查询3查询效率。再来看最后一个索引4,索引4和对查询1和查询4起效果,由于查询1已有索引3可用,故忽略对查询1的作用,现在只剩下对查询4的起作用,我们看查询4,索引3和索引4都对其产生效果,毫无疑问索引4对查询4效果更大一些,但考虑到Status列的低选择性和多维护一个索引的代价,索引3已能较好的完成查询4,所以删除索引4。

  这样一来针对Orders表的4个查询,我们经过对原来4个索引的优化调整后只保留了修改后的索引3,索引从4个变成一个,而查询效率方面却没有受较大的影响,达到了用尽可能少的索引完成尽可能多的查询的目的。

  在上面的演示中我们使用了OrderCode做为聚集索引,通过对非聚集索引的调整较好的完成了查询,在大说数情况下这样就可以ok了,现在我们考虑下若Orders表数据量较大,执行我们的查询4若返回结果达到几万、几十万甚至更多的时候,很可能会导致索引失效从而发生表扫描,这时除非我们队查询4使用的索引实现索引覆盖,不过这基本上不大现实。那如何解决这个问题呢?这时时间列上的聚集索引就开始显示威力了,修改我们的Orders表将聚集索引建立到PostTime列上

--删除原来的聚集索引主键 PK_Orders
ALTER TABLE dbo.Orders DROP CONSTRAINT PK_Orders

--创建非聚集索引主键 PK_Orders 
ALTER TABLE dbo.Orders ADD CONSTRAINT PK_Orders PRIMARY KEY NONCLUSTERED(OrderCode)

--在时间列PostTime上创建聚集索引
CREATE CLUSTERED INDEX IX_PostTime ON dbo.Orders(PostTime)

  修改后我们担心的书签查找问题彻底消失了,因为通常导致索引失效的原因都是过多的书签查找,发生大量书签查找时基本上和范围查询脱不开关系,大范围数据查询又肯定会用到时间列,所以推荐时间列做聚集索引。至于说修改了聚集索引后更新,订单查询效率会不会下降,对于这点基本上可以忽略,进行订单查询时一般数据量都会较小,那点书签查找开销完全可以忽略掉,比如我们的查询2。

  这时我们可能发现我们上面修改的索引3有个尴尬的现状,索引3的先导列PostTime现在成了聚集索引,那么索引3对查询1、查询3、查询4还有木有用,索引3还有木有存在的必要,关于这点一般来说呢非聚集索引最好不要用聚集索引做先导列,很可能建了等于白建这里只是个建议,那么若删除了索引3,查询1、查询3、查询4效率会如何,查询4效率肯定是会提升的、查询1、查询3需要实际测试,当然若可以的话把聚集索引建成联合的,把UserID放进去就不会有此问题了

--在时间列PostTime和UserID列上创建聚集索引
CREATE CLUSTERED INDEX IX_PostTimeUserID ON dbo.Orders(PostTime,UserID)

  当然了这种修改还得小心进行,根据实际需求灵活修改,理想的情况下是建立专门的只读数据库复制,在只读库上建立最适合范围查找的聚集索引,在主库上建立最有利于增、删、改的聚集索引,对实时性要求不高的查询全部转移到只读库上执行,相对而言需要大范围数据筛选的查询都不需要多好的实时性,尽可到只读库执行,而主库呢肯定是主要执行实时性要求高的小数据量查询。

  总结:

  聚集索引的优势在于大范围数据查询效率,因此需要将聚集索引建立在时间列、选择性相对较低并且经常会用于范围查询的列(选择性过低的如性别列肯定不行,过低的选择性列索引建了等于白建,比如你在性别列上集索引以为通过性别列起码一下过滤掉一半数据,范围大大减小你就大错特错了,这点选择性通常查询优化器会直接忽略掉,还不如个表扫描来的快),充分发挥聚集索引大范围数据查询优势。

  非聚集索引要尽量使用选择性较高的列以尽可能减少返回的数据量,利用组合索引提高索引的复用率,不要建过多的无用索引,如果发现某个表建了很多的非聚集索引,不妨把那些索引、查询摘出来分析合并下,减少没用索引的数量,以提高整体性能。

  索引建立还需根据实际需要进行选择,本文所述观点在能够适用于大多数情况,但建立好的索引不是一朝一夕能够做到的,理论上成立的事实际应用中往往会事与愿违,索引的有效性还要依靠数据库统计信息等综合考虑,故每当建立索引后一定要查看下查询计划,查看下IO开销,看看查询优化器是否按照我们预期的方式使用了索引。




 

posted @ 2012-07-09 09:59 顺其自然EVO 阅读(317) | 评论 (0)编辑 收藏

寻找用户轨迹的“探索性测试”

  国内的大部分公司在做交互设计的时候很大部分都是处于探索阶段,但是因为产品的商业价值很难允许失败,所以很多设计师对于交互设计的结果都很难确定,甚至会因此屈服于商业价值,从而导致了一个恶心循环。

  在上次的D4设计论坛中,针对于口碑网改版的设计方法,UT斯达康的设计经理提到了利用新旧入口的方式来进行用户测试,并提出了使用新界面提供老界面入口的方式进行用户测试。在我们设计产品的时候其实也可以利用产品的特性进行一些“探索性测试”。

  测试大致可以分成几种:一种是验证性的测试,在知道结果的前提下进行验证的测试,一般运用在学科领域的实验室中,更多的是对理论数据计算的结果进行验证;还有一种是探索性的测试,在未知或者并非全部了解的情况下进行探究的测试,主要是针对新产品新事物的一种尝试。探索性测试更多的使用在创业型产业领域中。

  Tidwell,J在《Designing Interfaces》中提到“在设计各种软件界面时,可以给用户留下实验性的通道来让他们探索和尝试,同时别让用户付出任何代价”解释了产品在使用探索性测试的时候应当注意的问题,在兼顾探索性测试的同时要避免给用户带来的阻力。

  在交互设计中,探索性测试可以分为以下几种:

  1、A-B test

  这种方式主要是在不明确产品的目标数据是否能够符合前期目标时所采用的一种模式。主要工作便是将产品的新旧版本平均随机的分配给用户进行使用,利用一至两天的时间进行数据检测,获得横向数据并进行比较可以得出新版本的优缺点以及确定修改的权重比。这种方式主要的优点是可以直接给出横向比较的情况,直观的了解新产品的优缺点,不过它的缺点是只限制于设计师对产品服务端更新优化的权限时刻保留,并不适合散发式单线使用产品(主要是指产品的控制权暴露在用户端并且没有和服务器端进行数据交互)。并且A-B test的模式会牺牲部分用户的使用状态,会给企业的用户使用度有所降低。

  2、新旧饱和测试

  新旧饱和测试主要是指推出新产品,但仍保留原产品的入口,进行用户测试。刚才说过,口碑的改版也是利用这种模式进行,而且还包括了淘宝、Google等网站也经常利用这种测试方法进行探索。它主要的优点是能够在新界面不影响用户的前提下,给用户返回旧界面的通道,减少用户牺牲,并且也尊重了合理撤销的理念。从用户角度出发进行的一些改版往往会不明白用户的使用情况到底如何,从商业角度来看新产品的价值点则是更高的,所以这种测试方式可以大大降低商业风险,并且利用“撤销概念”提高了用户体验。但它的缺点是浪费了产品空间,给服务端带来了数据兼容等后台的压力。

  3、引导性测试

  这种方式是指利用现场演示的方式为用户进行解说,更多是指还未上线前的一种用户测试。这种测试的优点是设计师能够更加贴近用户了解用户的想法。但是这种方式有很多局限性,首先是人员数量上比较少,其次是产品不够成熟,往往会带来很多用户并非真正理解产品,再者就是人工引导会给产品的可视化交互带来一定影响,无法得知用户的交互轨迹。这种测试很多情况下都是用于全新的产品。

  4、发散性测试

  这种方式也是比较传统的方式,主要是设计师不断借鉴其他产品的用户数据进行模拟从而得出测试预估结果,并且通过多种途径为预估结果进行数据监测。例如获得产品的使用量,用户的关注度,投票数等方式来了解真实环境中的用户模型,并更新改进原产品。它的优点是能够逐渐提高产品质量,以及设计师的预估能力。但这种模式主要缺点是周期长,预估能力要求高,二期修改成本大,对于现有阶段的公司来讲虽然用的比较多,但却不是最可取的一种方式。

  这几种测试方式,并非等同于可用性和易用性的用户测试,而是对目标数据的一种产品设计预估测试。虽然目前很多公司对于交互设计还是个探索,但是如果合理利用这几种“探索性测试”的方式来获得更多宝贵数据的话,交互设计的路应该会走的更顺一些。

posted @ 2012-07-06 09:57 顺其自然EVO 阅读(193) | 评论 (0)编辑 收藏

Web测试兼容性

  随时操作系统,浏览器越来越多样性,导致软件兼容性测试在目前软件测试领域占有很重要的地位,无论是B/S架构还是C/S架构的软件都需要进行兼容性测试,为了充分保证产品的平台无关性,使用户充分感受到软件的友好。

  Web兼容性测试大致有如下几个分类:

  1、操作系统/平台兼容:

  常见的操作系统有windowsunix、linux等,对于普通用户来讲,最常用的是Windows操作系统。Windows操作系统包括Windows XP,windows 2003,vista,Win2000/NT,Windows9x等等,每个软件产品的兼容性测试是一个循序渐进的过程。

  就阿里旺旺客户端来说,针对阿里旺旺用户的使用人群,已经市面上主流的操作系统和投诉问题中涉及到的操作紫铜展开专项兼容性测试,累计的操作系统兼容性测试范围有:

操作系统

版本

备注

Windows XP

Home家庭版(32bit

主流操作系统

Professional专业版(32bit

主流操作系统

Windows Vista

Home Basic初级家庭版(32bit

主流操作系统

Ultimate终极版(32bit

主流操作系统

Windows 7

Home Basic初级家庭版(32bit

品牌机预装主流操作系统

Home Basic初级家庭版(64bit

品牌机预装主流操作系统

Ultimate旗舰版(32bit

D版主流操作系统

Ultimate旗舰版(64bit

D版主流操作系统

  针对每次迭代的客户端版本,一般都会根据用户操作系统的常用频度,涉及兼容性策略,试试兼容性测试。所以兼容性测试的工作量一般都很大,对于迭代版本的全量的兼容性测试人工实施的能力很难达到有效的成果。如果能够研究利用自动化测试

  2、不同浏览器之间兼容:

  浏览器是Web系统中核心的组成构件,来自不同厂家的浏览器对javascript、ActiveX或不同的HTML规格有不同的支持,即时是同一厂家的浏览器,也存在不同的版本的问题。目前主流的浏览器玉两大类,一类是IE内核的浏览器,一类则是非IE内核的浏览器,具体的主流浏览器有IE,Firefox,Chrome、Opera、360浏览器,搜狗浏览器等,针对这些主流的浏览器必须进行兼容性测试。阿里旺旺客户端相关的跳转页面目前浏览器兼容性测试范围有:


  由于阿里旺旺的内嵌页面都是引用的是IE内核,所以针对阿里旺旺内嵌页面,我们主要测试IE6,7,8,9。

  3、不同分辨率之间兼容:

  分辨率的测试是为了页面版在不同的分辨率模式下能正常显示,字体符合要求而进行的测试。现在常见的分辨率是1280*1024、1027*768、800*600。对于常见的分辨率,测试必须保证测试通过,对于其他分辨率,原则上也应该尽量保证。根据具体情况进行取舍,保留至专项兼容性测试时实施。

  当然,针对阿里旺旺客户端的内嵌页面,我们还需要根据不同的业务场景考虑到的兼容性问题。比如:不同版本客户端的兼容性(向上兼容,向下兼容)、账号类型的兼容性(买家账号,卖家账号,E客服子账号以及特殊的账号)。

  目前,我们主要涉及到的具体的兼容性测试总结就以上所呈现的,当然在软件领域,创新很多很快,软件测试技术相继也要不断的提高,充分发挥发散的思维,后续我们要不断总结学习经验,使产品测试更充分更有效,提高产品整体质量是我们的责任,为用户生活带来喜悦与便捷是我们的态度。




posted @ 2012-07-06 09:54 顺其自然EVO 阅读(1266) | 评论 (0)编辑 收藏

每日构建和冒烟测试

  谈每日构建都会连带谈冒烟测试这个词。每日构建不是简单的指每日编译,编译和构建完成后必须对增加的新功能点进行系统测试,对已经测试过的功能点进行冒烟测试。每日构建是微软比较推荐的最佳实践,强调测试的早期介入和持续的版本集成。

  每日构建和冒烟测试的优点主要有:

  1、进度可见并可以控制到1-2天的细粒度,很容易看到进度的偏差

  2、及早的发现开发BUG和缺陷并分析解决,对开发人员的一种监督和促进,提高软件质量

  3、由于将大集成分解到每日构建中的小集成,避免了传统产品集成或集成测试时候出现的严重问题的可能。

  4、在项目中宣灌质量意识,强调第一次就把事情做好,而不是等测试来帮你发现问题

  每日构建和冒烟测试也存在一些风险和缺陷,具体主要有:

  1、给开发人员太大压力,开发每天都在较紧张环境中工作

  2、需要额外的测试人力资源和每日构建硬件环境的投入

  3、开发人员不能专注,既要分心去修改BUG,又要开发新的功能点

  4、对开发负责人要求更好,需要将功能细化到1-2天的有明确输出的功能点

  5、开发需要投入额外的精力来保证每日构建顺畅

  适用场景:

  1、对进度偏差控制和要求很高的项目

  2、开发检查点和里程碑制定的很细致的项目

  3、采用增量和迭代开发的项目,快速和敏捷开发的项目

  每日构建提前需要进行的准备工作:

  1、对开发进度计划的要求,需要细化出每1-2天的开发进度计划,可以到一个很小的功能点。

  2、对每日构建测试计划的要求,需要根据开发进度计划来安排冒烟测试和系统测试进度计划。

  3、需要提前准备好每日构建的环境(每日构建必须是独立的环境)

  每日构建和冒烟测试工作的实现可以人工来实现,但更多的需要借助些自动化的工具来完成。对于每日构建一般要提前编写好每日够建的脚本,可以借助Ant或NAnt构建工具来完成。每日构建脚本的复杂性跟项目或系统本身复杂性相关,对于简单的只有一个项目的解决方案,可能构建脚本会很简单,而对于较复杂的系统或项目构建脚本将会教复杂。NAnt是一个强大的通过构建脚本自动编译的工具,像我现在的项目在NAnt里面会做如下事情,而这个即使打开解决方案来编译也无法做到。

  1、调用批文件重新自动生成数据访问层组件

  2、创建相关的部署需要的cs_client,bs_client,server,service相关目录并拷贝公用文件


  3、按照公用项目->逻辑层->界面层顺序和项目间依赖关系对各个项目逐一编译

  4、调用外部工具soapsuds生成数据访问dll的代理类文件,逻辑层重新引用代理类进行编译(分布式部署需要)

  5、引用3,4步需要的dll对Web项目进行编译

  6、拷贝编译结果到相关的输出目录

  每日构建和每日编译的最大区别就在于是否进行了冒烟测试,系统必须通过了冒烟测试才能够算每日构建成功。而测试人员人工介入的测试是基于冒烟测试通过的基础上面的。这里很简单一个例子,如我们NAnt配置文件忘记拷贝一个公共文件到server目录了,这个时候每日编译可能是通过的,但如果把这个版本部署出去测试无法进行测试的。或者说冒烟测试的一个重要作用就是要彻底解决由于构建自身原因引起的各种缺陷或Bug。

  冒烟测试由于要验证整个编译的正确性,因此冒烟测试必须是针对整个系统进行冒烟测试。但冒烟测试只需要关注系统的主体功能即可,通过冒烟测试并不是说系统没有BUG,只是说通过了冒烟测试后可以说系统是一个稳定的版本,说系统的每日构建是成功了,代表系统可以转交专门的测试人员进行测试了。冒烟测试工作一般要采用自动化来进行,可以借助如LoadRunner等工具来录制自动化测试脚本,冒烟测试的脚本应该由专门的测试人员来维护,而且随着测试的进展冒烟测试脚本也应该是不断增加和补充的。

  对于每日构建失败,直接责任的开发人员需要程度责任并付出代价。微软顾问经常爱举的一个例子就是凌晨2,3点开发人员被叫到公司解决每日构建失败的问题的案例。实际操作可能很难,但对构建造成影响的必须要承担应有的责任。

  每日构建一般要配合使用源代码管理工具,而构建时间一般安排在每天下班后或晚上进行。开发人员需要保证每天检入的代码是能够顺利编译通过的,并保证在本机已经做了相关测试。每日构建并不是一定要要求每天都有新的功能点完成,如果今天开发完成的东西不是一个独立的可以提交测试的功能点,这个时候当天的源代码最好不要检入。代码的检入周期一般要在2-3天内,如果周期再长基本上就达不到每日构建的作用了。

  每日构建必须有独立和专门的构建服务器和构建环境。构建服务器和构建环境与测试环境的最大区别在于构建环境是完全Copy开发环境,单独出构建环境目的是保证构建过程不和开发环境和过程冲突。如果条件不允许的话可以将构建环境和测试环境合并,但构建环境必须和开发环境分离。

  每日构建的成功要素:

  1、每天都进行编译和冒烟测试

  2、冒烟测试脚本随着测试的进度不断完善和补充

  3、构建成功在项目中拥有较高的优先级

  4、通过过程的制定保证构建失败更多的是因为异常因素而非规则不清

  5、在压力下不要抛弃过程

posted @ 2012-07-06 09:50 顺其自然EVO 阅读(815) | 评论 (0)编辑 收藏

SQL Server查询性能优化之创建合理的索引(上)

本文主要作为优化查询性能的一些知识储备,感觉知识点有些散,不知道起啥名字好,独立成文又没有达到把每个点都说透彻那样的高度,且就当做创建合理索引的一个楔子把。本文对实际应用没有太大的指导意义,但可以加深我们对SQL Server理解,夯实我们的基本功,就像小说里面的武功一样,没有足够的内功基础,给你再好的秘籍你也成不了武林高手。

  序言

  写这篇文章时表示鸭梨很大,主要是对SQL Server的认识很有限,远远不足把这个话题说清楚,不过还是鼓起勇气写出来,也算作自己对索引认识的一个总结。索引这潭水太深了,应用场景不同,所建立的索引在有些情况下运行良好,有些情况下可能完全无效。而对于索引理解、认识层次不同,怎样建才比较合理的也是众说分云,用万金油的说法就是没有最合理的只有最合适的。一般来说最懂数据库的当属DBA,不过DBA却不懂业务,一般除了一些核心业务模块表建立及索引维护有DBA完成外,大多数情况下索引、SQL维护都是有开发人员完成的,因此我们通常认为的索引建立、优化都是有开发人员完成的(并不是我无视DBA,事实就是这个情况),可能有人疑惑了,DBA不维护索引、不写SQL那他们都干嘛吃去了,这个俺还真不知道,不过DBA很忙、很累我是知道的,估计、可能、大概会做以下事情:数据库并发、分发复制、性能监控、数据迁移、备份、日常维护、索引、SQL调优等等,DBA童鞋别喷我,我是真的不知道,DBA童鞋们可以留言告诉我下哈。

  下面简单说一些暂时想到的对使用索引影响较大的几个注意点

  页是SQL Server存储数据的基本单位,大小为8KB。

  请一定要记住,页是SQL Server进行数据读写的最小I/O单位,而不是行。SQL Server中一个页大小为8KB,每8个页形成一个区,每页8KB,其中页头占用96个字节,页尾的行指示器占用2个字节,还有几个保留字节,也就是一个页8192个字节,能用了存储数据的实际约8000个字节,8000个字节一般可以存储很多行数据。即便SQL Server只访问一行数据,它也要把整个页加载到缓存并从缓存读取数据,我们通常所说的开销主要就是I/O开销,这点不少人都没有清醒的认知。

  认识窄索引

  很多书籍和文章都写过索引要使用窄索引,窄索引是个什么东东呢,大白话就是把索引建在字节长度比较小的列上,比如int占用4个字节,bigint占用8个字节,char(20)占用20个字节nchar(20)最占用40个字节,那么int 相对于bigint来说就是窄了(占用字节数更少),bigint比char(20)也要窄,char(20)和nchar(20)相比要窄(nchar(20)每个字符占用2个字节)。

  明白了啥是窄索引我们来说下为什么要使用窄索引,我们知道数据存储和读取的最小单位是页,一个页8K大小,当使用比较窄的列做索引列时,每个页能存储的数据就更多,以int和bigint为例,一个8K的页大约能存储8*1024/4(int 4个字节)=2048(实际值要比这个数字小)条数据,使用bigint大约能存储8*1024/8(bigint为8个字节)=1024(实际值要比这个数字小)条数据,也就是说索引列的长度也小,每个页能存储的数据也就越多,反过来说就是存储索引所需要的页数也就越少,页数少了进行索引查找时需要检索的页自然也就少了,检索页数少了IO开销也就随之减少,查询效率自然也就高了。

  认识索引的二叉树级数

  SQL Server中所有的索引都是平衡二叉树结构,平衡树的意思是所有叶子节点到根节点的距离都相同,SQL Server进行索引查找时总是从索引的根节点开始,并从根跳到下一级的相应页,并继续从一个级别跳到下一个级别,直到达把可以查找键的叶子页。所有叶级节点到底跟的距离都是相同的,这意味着一次查找操作在叶读取上的成本正好是页的级数。索引级数大多为2级到4级,2级索引大约包含几千行,3级索引大约4 000 000行,4级索引能容纳约4 000 000 000 行,这点上聚集索引和非聚集索引上是一样的。一般来说对于小表来说索引通常只有2级,对于大表通常包含3级或4级。

  索引级数也就意味着一次索引查找的最小开销,比如我们建立一个User表

CREATE     TABLE Users
(
    UserID INT IDENTITY,
    UserName nvarchar(50),
   Age INT,
   Gender BIT,
    CreateTime DateTime
)

--在UserID列上创建聚集索引 IX_UserID
CREATE UNIQUE CLUSTERED INDEX IX_UserID ON dbo.Users(UserID)
--插入示例数据
insert into Users(UserName,Age,Gender,CreateTime)
select N'Bob',20,1,'2012-5-1'
union all
select N'Jack',23,0,'2012-5-2'
union all
select N'Robert',28,1,'2012-5-3'
union all
select N'Janet',40,0,'2012-5-9'
union all
select N'Michael',22,1,'2012-5-2'
union all
select N'Laura',16,1,'2012-5-1'
union all
select N'Anne',36,1,'2012-5-7'

  我们执行查询

SELECT * FROM dbo.Users WHERE UserID=1

  可以看到输出信息为

(1 行受影响)
表 'Users'。扫描计数 0,逻辑读取 2 次,物理读取 0 次,预读 0 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。

  当表数据量增多至几千条时,执行上述查询逻辑读依然为2,当数据量到达百万级别时逻辑读会变成3,当到达千万、亿级别时,逻辑读就会变成4,有兴趣的童鞋可以亲自去试验下。

  认识书签查找的开销

  当使用非聚集索引时,若查询条件没有实现索引覆盖就会形成书签查找,那么一次书签查找的开销是多少呢?答案是不一定,一般为1到4次逻辑读,对于堆表(无聚集索引的表)来说,一次书签查找只需要一次逻辑读,对于非堆表(有聚集索引的表)来说一次书签查找的逻辑读次数为聚集索引的级数,在索引结构我们简单说了下大多数聚集索引的级数为2-4级,也就是说对于非堆表来说一次逻辑读的开销为2-4次逻辑读,下面我们做具体测试

  创建非聚集索引 IX_UserName

CREATE INDEX IX_UserName ON dbo.Users(UserName)

  执行查询

SELECT UserID,UserName FROM dbo.Users WITH(INDEX(IX_UserName))WHERE UserName =('Bob')

  由于我们的查询实现了索引覆盖,没有书签查找,获取一条数据需要2次逻辑读

(1 行受影响)
表 'Users'。扫描计数 1,逻辑读取 2 次,物理读取 0 次,预读 0 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。

(1 行受影响)

  修改查询,返回列中增加CreateTime,这样就无法实现索引覆盖

SELECT UserID,UserName,CreateTime FROM dbo.Users WITH(INDEX(IX_UserName))WHERE UserName =('Bob')

  可以看到这时发生了书签查找,同样返回一条数据,逻辑读达到了4次(索引查找2次,书签查找2次),由于我们的表Users为非堆表,故一次书签查找需要2次(聚集索引IS_UserID的级数为2)逻辑读

(1 行受影响)
表 'Users'。扫描计数 1,逻辑读取 4 次,物理读取 0 次,预读 0 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。

(1 行受影响)

  然后我们继续测试堆表的书签查找开销,删除表Users的聚集索引IX_UserID,使其变为堆表

DROP INDEX IX_UserID ON dbo.Users

  再次执行我们的查询,可以看到逻辑读变成了3次(索引查找2次,书签查找1次),想想为什么堆表的书签查找次数少呢?

SELECT UserID,UserName,CreateTime FROM dbo.Users WITH(INDEX(IX_UserName))WHERE UserName =('Bob')

(1 行受影响)
表 'Users'。扫描计数 1,逻辑读取 3 次,物理读取 0 次,预读 0 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。

(1 行受影响)


  使用索引时的随机读

  嗯,关于随机读我现在也有些迷糊,只是大概的知道发生随即读时即便需要的数据就存在同一页上,也会发生多次读取,而不是一次拿到整页数据后进行筛选。当进行where in查找或发生书签查找时,一定会使用随机读

  首先我们看看聚集索引的随即读表现

--创建聚集索引IX_UserID
CREATE UNIQUE CLUSTERED INDEX IX_UserID ON dbo.Users(UserID)

  执行如下查询,可以发现在聚集索引上面使用where in时不管有没有找到记录都会进行聚集索引查找,而且查找次数固定为where in里面的条件数*索引级数,不知道为什么明明索引扫描有着更高的效率,查询优化器还是选择聚集索引查找,有知道的朋友还请告知下哈

--这个聚集索引扫描,返回记录7条,逻辑读2次
SELECT * FROM dbo.Users
--这个聚集索引查找,返回记录3条,逻辑读2次
SELECT * FROM dbo.Users WHERE UserID<=2
--这个聚集索引查找,返回记录3条,逻辑读6次
SELECT * FROM dbo.Users WHERE UserID IN(1,2)
--这个聚集索引查找,返回记录0条,逻辑读6次
SELECT * FROM dbo.Users WHERE UserID IN(10,20,22)

(7 行受影响)
表 'Users'。扫描计数 1,逻辑读取 2 次,物理读取 0 次,预读 0 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。

(1 行受影响)

(3 行受影响)
表 'Users'。扫描计数 1,逻辑读取 2 次,物理读取 0 次,预读 0 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。

(1 行受影响)

(3 行受影响)
表 'Users'。扫描计数 3,逻辑读取 6 次,物理读取 0 次,预读 0 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。

(1 行受影响)

(0 行受影响)
表 'Users'。扫描计数 3,逻辑读取 6 次,物理读取 0 次,预读 0 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。

(1 行受影响)

  我们再来看下非聚集索引的随机读,当然我这里为了演示特意使用了索引提示,实际应用中没事千万别加索引提示,当使用非聚集索引时查询优化器发现使用索引后效率更低时会放弃索引转为使用表扫描,我们这个例子中若去掉索引提示的话使用表扫描仅需要2次逻辑读就可以完成查询,这里仅仅是为了演示

--非聚集索引查找,返回记录2,逻辑读2
SELECT UserID,UserName FROM dbo.Users WITH(INDEX(IX_UserName))WHERE UserName  LIKE 'J%'
--非聚集索引查找,返回记录2,逻辑读4
SELECT UserID,UserName FROM dbo.Users WITH(INDEX(IX_UserName))WHERE UserName IN('Bob','Jack')

--非聚集索引查找+书签查找,返回记录2,逻辑读6
SELECT UserID,UserName,CreateTime FROM dbo.Users WITH(INDEX(IX_UserName))WHERE UserName  LIKE 'J%'

--非聚集索引查找+书签查找,返回记录0,逻辑读2(索引查找2*1+书签查找2*0)
SELECT UserID,UserName,CreateTime FROM dbo.Users WITH(INDEX(IX_UserName))WHERE UserName IN('Rabbit')
--非聚集索引查找+书签查找,返回记录1,逻辑读4(索引查找2*1+书签查找2*1)
SELECT UserID,UserName,CreateTime FROM dbo.Users WITH(INDEX(IX_UserName))WHERE UserName IN('Bob')
--非聚集索引查找+书签查找,返回记录2,逻辑读8(索引查找2*2+书签查找2*2)
SELECT UserID,UserName,CreateTime FROM dbo.Users WITH(INDEX(IX_UserName))WHERE UserName IN('Bob','Jack')


(2 行受影响)
表 'Users'。扫描计数 1,逻辑读取 2 次,物理读取 0 次,预读 0 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。

(1 行受影响)

(2 行受影响)
表 'Users'。扫描计数 2,逻辑读取 4 次,物理读取 0 次,预读 0 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。

(1 行受影响)

(2 行受影响)
表 'Users'。扫描计数 1,逻辑读取 6 次,物理读取 0 次,预读 0 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。

(1 行受影响)

(0 行受影响)
表 'Worktable'。扫描计数 0,逻辑读取 0 次,物理读取 0 次,预读 0 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。
表 'Users'。扫描计数 1,逻辑读取 2 次,物理读取 0 次,预读 0 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。

(1 行受影响)

(1 行受影响)
表 'Users'。扫描计数 1,逻辑读取 4 次,物理读取 0 次,预读 0 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。

(1 行受影响)

(2 行受影响)
表 'Users'。扫描计数 2,逻辑读取 8 次,物理读取 0 次,预读 0 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。

(1 行受影响)

  总结:

  认识书索引的查找开销、书签查找的开销、随机读的影响对我们具体创建索引和编写SQL有着积极的影响,毕竟对查询的的认识更加清楚了,我们在写索引和SQL时候才有更有针对性,最起码我们又知道了一个尽量不适用where in的理由,为什么要尽量规避书签查找,聚集索引查找不见得就一定高效,顺便留个问题:聚集索引扫描和非聚集索引扫描哪个有着更高的效率,什么情况下会发生非聚集索引扫描?

  嗯,暂且写到这里,还是脑子里的墨水太少了,写点东西就感觉脑子里空荡荡的......

  原文出自:http://www.cnblogs.com/lzrabbit/archive/2012/06/11/2517963.html






posted @ 2012-07-06 09:48 顺其自然EVO 阅读(243) | 评论 (0)编辑 收藏

浅谈如何用Java操作MongoDB?

 NoSQL数据库因其可扩展性使其变得越来越流行,利用NoSQL数据库可以给你带来更多的好处,MongoDB是一个用C++编写的可度可扩展性的开源NoSQL数据库。本文主要讲述如何使用Java操作MongoDB以及了解MongoDB如何进行日常的数据库操作。

  文章内容如下:

  第一步:安装MongoDB

  无需太多的繁杂步骤,你只要在MongoDB官方网站查看安装说明,根据自己的操作系统进行选择适应的版本即可。

  第二步:启动MongoDB服务器

  这一步也很简单。运行mongod.exe文件里的bin文件夹(我使用的是Windows OS系统),并启动MongoDB服务器。

  在默认的情况下服务器将启动端口27017,你需要在安装过程中创建将数据存储在/data/db目录里。

  第三步:启动MongoDB shell指令

  你可以通过运行mongo.exe文件来启动MongoBD shell。

  第四步:利用MongoDB创建数据库

  利用MongoDB在MongoDB shell中输入以下内容建立一个名为“company”的数据库。

use company

  记住,除非你在MangoDB里保存了一些东西,否则它不会自动为你保存。

  使用下面的命令帮你查看可用的数据库,它会显示“company”尚未被创建。

show dbs;

  第五步:在MongoDB中保存数据

  使用下面的命令来保存employee 数据代表一个collection,将其命名为employees

employee = {name : "A", no : 1}
db.employees.save(employee)

  通过使用下面的命令来查看collection里的数据。

db.users.find();


  如何使用Java操作MongoDB?

  下面是是一段简单的Java代码,你可以在这里获得mongo-java驱动。很简单,只需要使用下面的代码,重复上面的操作即可。

  1. package com.eviac.blog.mongo;    
  2.     
  3. import java.net.UnknownHostException;    
  4.     
  5. import com.mongodb.BasicDBObject;    
  6. import com.mongodb.DB;    
  7. import com.mongodb.DBCollection;    
  8. import com.mongodb.DBCursor;    
  9. import com.mongodb.Mongo;    
  10. import com.mongodb.MongoException;    
  11.     
  12. public class MongoDBClient {    
  13.     
  14.  public static void main(String[] args) {    
  15.     
  16.   try {    
  17.     
  18.    Mongo mongo = new Mongo("localhost", 27017);    
  19.     
  20.    DB db = mongo.getDB("company");    
  21.     
  22.    DBCollection collection = db.getCollection("employees");    
  23.     
  24.    BasicDBObject employee = new BasicDBObject();    
  25.    employee.put("name", "Hannah");    
  26.    employee.put("no", 2);    
  27.     
  28.    collection.insert(employee);    
  29.     
  30.    BasicDBObject searchEmployee = new BasicDBObject();    
  31.    searchEmployee.put("no", 2);    
  32.     
  33.    DBCursor cursor = collection.find(searchEmployee);    
  34.     
  35.    while (cursor.hasNext()) {    
  36.     System.out.println(cursor.next());    
  37.    }    
  38.     
  39.    System.out.println("The Search Query has Executed!");    
  40.     
  41.   } catch (UnknownHostException e) {    
  42.    e.printStackTrace();    
  43.   } catch (MongoException e) {    
  44.    e.printStackTrace();    
  45.   }    
  46.     
  47.  }    
  48.     
  49. }

  结果如下:

  1. { "_id" : { "$oid" : "4fec74dc907cbe9445fd2d70"} , "name" : "Hannah" , "no" : 2}    
  2. The Search Query has Executed!

  小结:

  随着互联网Web2.0网站的兴起,非关系型的数据库现在成了一个极其热门的新领域,非关系数据库产品的发展也非常迅速。本文浅显的谈及了如何使用Java操作MongoDB以及了解MongoDB如何进行日常的数据库操作的问题。如果您是这方面的专家不妨与我们分享下。





posted @ 2012-07-06 09:44 顺其自然EVO 阅读(217) | 评论 (0)编辑 收藏

仅列出标题
共394页: First 上一页 308 309 310 311 312 313 314 315 316 下一页 Last 
<2024年11月>
272829303112
3456789
10111213141516
17181920212223
24252627282930
1234567

导航

统计

常用链接

留言簿(55)

随笔分类

随笔档案

文章分类

文章档案

搜索

最新评论

阅读排行榜

评论排行榜