查看SQL语句执行时间

通过设置STATISTICS我们可以查看执行SQL时的系统情况。选项有PROFILE,IO ,TIME。介绍如下:

SET STATISTICS PROFILE ON:显示分析、编译和执行查询所需的时间(以毫秒为单位)。
SET STATISTICS IO ON:报告与语句内引用的每个表的扫描数、逻辑读取数(在高速缓存中访问的页数)和物理读取数(访问磁盘的次数)有关的信息。
SET STATISTICS TIME ON:显示每个查询执行后的结果集,代表查询执行的配置文件。

使用方法:打开SQL SERVER 查询分析器,输入以下语句:

SET STATISTICS PROFILE ON
SET STATISTICS IO ON
SET STATISTICS TIME ON
GO /*–你的SQL脚本开始*/
SELECT [TestCase] FROM [TestCaseSelect]
GO /*–你的SQL脚本结束*/
SET STATISTICS PROFILE OFF
SET STATISTICS IO OFF
SET STATISTICS TIME OFF

效果如图所示:

 查看SQL语句执行时间

MSMQ消息队列

一、引言

  Windows Communication Foundation(WCF)是Microsoft为构建面向服务的应用程序而提供的统一编程模型,该服务模型提供了支持松散耦合和版本管理的序列化功能,并提供了与消息队列(MSMQ)、COM+、Asp.net Web服务、.NET Remoting等微软现有的分布式系统技术。利用WCF平台,开发人员可以很方便地构建面向服务的应用程序(SOA)。可以认为,WCF是对之前现有的分布式技术(指的是MSMQ、.NET Remoting和Web 服务等技术)的集成和扩展,既然这样,我们就有必要首先了解下之前分布式技术,只有这样才能更深刻地明白WCF所带来的好处。今天就分享下MSMQ这种分布式技术。

二、MSMQ的介绍

   MSMQ全称是Microsoft Message Queue——微软消息队列。它是一种异步传输模式,可以在不同的应用之间实现相互通信,相互通信的应用可以分布在同一台机器上,也可以分布于相连的网络空间中的任一位置。

2.1 MSMQ 工作原理

  MSMQ的实现原理是:消息的发送者把自己想要发送的信息放入一个容器,然后把它保存到一个系统公用空间的消息队列中,本地或异地的消息接收程序再从该队列中取出发给它的消息进行处理。

  消息队列是一个公用存储空间,它可以存在于内存中或物理文件中,因此,消息以两种方式发送,即快递方式和可恢复模式。它们的区别是消息存储位置的不同,快递方式,为了消息的快速传递,所以把消息放置在内存中,而不放在物理磁盘上,以获得较高的处理能力;而可恢复模式在传送过程的每一步骤中,都把消息写入物理磁盘上,这样当保存消息队列的机器发生故障而重新启动后,可以把发送的消息恢复到故障发送之前的状态,以获得更好的消息恢复能力。消息队列可以放在发送方、接收方所在的机器上,也可以单独放置在另外一台机器上。另外,采用消息队列机制,发送方不必要担心接收方是否启动,是否发生故障等因素,只要消息成功发送出去,就可以认为处理完成,而实际上对方可能甚至未开机,或者实际消息传递到对方可能在第二天。MSMQ机制类似QQ消息传递机制。下图演示了MSMQ的实现原理。

MSMQ消息队列

  MSMQ中主要有两个概念。

  •   一个是消息Message:Message是通信双方需要传递的消息,它可以是文本、图片、视频等。消息包含发送和接收者的标识,只有指定的用户才能取得消息。
  •   一个是队列Queue:用来保存消息的存储空间,MSMQ中主要包括以下几种队列类型:
    • 公共队列:在整个消息队列网络中复制,有可能由网络连接的所有站点访问。路径格式为:机器名称/队列名称
    • 专用队列(或叫私有队列):不在整个网络中发布,它们仅在所驻留的本地计算机上可用,专用队列只能由知道队列的完整路径名称或标签的应用程序访问。路径格式为:机器名称/Private$/队列名称
    • 日志队列:包含确认在给定“消息队列中发送的消息回执消息”。路径格式为:机器名称/队列名称/Journal$
    • 响应队列:包含目标应用程序接收到消息时返回给发送应用程序的响应消息,包括机器日志队列、机器死信队列和机器事务死信队列。

      • 机器日志队列对应的格式为:机器名称/Journal$;
      • 机器死信队列对应的格式为:机器名称/Deadletter$;
      • 机器信道死信队列对应的格式为:机器名称/XactDeadletter$。

 

2.2 队列引用说明

  当创建了一个MessageQueue实例之后,就应指明和哪个队列进行通信,在.NET中有3种访问指定消息队列的方法:

  • 使用路径,消息队列的路径被机器名和队列名唯一确定,所以可以用消息队列路径来指明使用的消息队列。
  • 使用格式名(format name),它是由MSMQ在消息队列创建时生成的唯一标识,个使命不由用户指定,而是由队列管理者自动生成的GUID。
  • 使用标识名(label),它是消息队列创建时由消息管理者指定的带有意义的名字。

 

三、消息队列的优缺点

   采用消息队列的好处是:由于是异步通信,无论是发送方还是接收方都不同等待对方返回成功消息,就可以执行余下的代码,大大提高了处理的能力;在信息传递过程中,具有故障恢复能力;MSMQ的消息传递机制使得通信的双方具有不同的物理平台成为可能。

  消息队列缺点是不适合Client需要Server端实时交互情况,大量请求时候,响应可能延迟。

四、利用MSMQ开发分布式应用

4.1 环境准备

   要想在.NET平台进行MSMQ的开发,需要安装消息队列,你需要打开控制面板->程序->打开或关闭Windows功能,勾选消息队列服务所有选项,具体操作如下图所示:

MSMQ消息队列

  勾选完之后点击确定之后,可以在我的电脑->管理->服务和应用程序->消息队列 看到下面的图:

MSMQ消息队列

  看到上面这个图代表你已经成功配置了MSMQ的开发环境,下面就可以使用Visual Studio 进行开发。注意,对特定类型队列的操作代码,一定要成功安装对应的队列类型。

4.2 使用MSMQ开发分布式应用

  首先,实现服务器端。创建一个控制台项目,添加System.Messaging引用,因为消息队列的类全部封装在System.Messaging.dll程序集里。具体服务端的代码如下:

1 using System;  2 using System.Messaging;  3   4 namespace MSMQServer  5 {  6     class Program  7     {    8         static void Main(string[] args)  9         { 10             // 创建一个公共队列,公共队列只能创建在域环境里 11             //if (!MessageQueue.Exists(@"./LearningHardMSMQ")) // 判断此路径下是否已经有该队列 12             //{ 13             //    using (MessageQueue mq = MessageQueue.Create(@"./LearningHardMSMQ")) 14             //    { 15             //        mq.Label = "LearningHardQueue"; // 设置队列标签 16             //        Console.WriteLine("已经创建了一个公共队列"); 17             //        Console.WriteLine("路径为:{0}", mq.Path); 18             //        Console.WriteLine("队列名字为:{0}", mq.QueueName); 19             //        mq.Send("MSMQ Message", "Leaning Hard"); // 发送消息 20             //    } 21             //} 22  23             //if (MessageQueue.Exists(@"./Private$/LearningHardMSMQ")) 24             //{ 25                   // 删除消息队列 26             //    MessageQueue.Delete(@"./Private$/LearningHardMSMQ"); 27             //} 28             // 创建一个私有消息队列 29             if (!MessageQueue.Exists(@"./Private$/LearningHardMSMQ")) 30             { 31                 using (MessageQueue mq = MessageQueue.Create(@"./Private$/LearningHardMSMQ")) 32                 { 33                     mq.Label = "LearningHardPrivateQueue";  34                     Console.WriteLine("已经创建了一个私有队列"); 35                     Console.WriteLine("路径为:{0}", mq.Path); 36                     Console.WriteLine("私有队列名字为:{0}", mq.QueueName); 37                     mq.Send("MSMQ Private Message", "Leaning Hard"); // 发送消息 38                 } 39             } 40  41             // 遍历所有的公共消息队列 42             //foreach (MessageQueue mq in MessageQueue.GetPublicQueues()) 43             //{ 44             //    mq.Send("Sending MSMQ public message" + DateTime.Now.ToLongDateString(), "Learning Hard"); 45             //    Console.WriteLine("Public Message is sent to {0}", mq.Path); 46             //} 47             48             if (MessageQueue.Exists(@"./Private$/LearningHardMSMQ"))  49             { 50                 // 获得私有消息队列 51                 MessageQueue mq = new MessageQueue(@"./Private$/LearningHardMSMQ"); 52                 mq.Send("Sending MSMQ private message" + DateTime.Now.ToLongDateString(), "Leaning Hard"); 53                 Console.WriteLine("Private Message is sent to {0}", mq.Path); 54             } 55  56             Console.Read(); 57         } 58     } 59 }

 

  服务器端代码需要注意的是,公共队列只能在域环境中创建,由于我的个人电脑没有加入域环境,所以不能创建公共队列,从开始的消息队列的截图也可以看出,在图中并没有安装公共队列。

  实现完服务器端之后,自然就是完成客户端。MSMQ程序的原理主要是:服务器端把消息发送到共享的消息队列中,然后,客户端从这个共享的消息队列中取出消息进行处理。具体客户端的实现代码如下所示:

1 using System;  2 using System.Messaging; // 需要添加System.Messaging引用  3   4 namespace MSMQClient  5 {  6     class Program  7     {  8         static void Main(string[] args)  9         { 10             if (MessageQueue.Exists(@"./Private$/LearningHardMSMQ")) 11             { 12                 // 创建消息队列对象 13                 using (MessageQueue mq = new MessageQueue(@"./Private$/LearningHardMSMQ")) 14                 { 15                     // 设置消息队列的格式化器 16                     mq.Formatter = new XmlMessageFormatter(new string[] { "System.String" }); 17                     foreach (Message msg in mq.GetAllMessages()) 18                     { 19                         Console.WriteLine("Received Private Message is: {0}", msg.Body); 20                     } 21  22                     Message firstmsg = mq.Receive(); // 获得消息队列中第一条消息 23                     Console.WriteLine("Received The first Private Message is: {0}", firstmsg.Body); 24                 } 25             } 26             Console.Read(); 27         } 28     } 29 }

4.3 运行演示

  经过上面步骤,我们已经完成了MSMQ分布式程序的实现了,下面看看如何运行该程序来查看效果。

  首先,自然要启动服务器,右键MSMQServer项目->调试->启动新实例来启动服务器,具体步骤如下图所示:

MSMQ消息队列

  运行成功之后,你将到服务器发送消息成功的控制台界面,效果图如下所示:

MSMQ消息队列

  接下来运行客户端来从消息队列中取得消息并显示在控制台中,采用和服务器相同的方式来启动客户端,右键MSMQClient->调试->启动新实例,看到客户端的效果如下图所示:

MSMQ消息队列

  从上图可以看出,客户端确实成功地取得了消息队列中的消息。

    以上MSMQ程序需要特别注意是:MessageQueue.Receive()是取出消息队列中队列中的第一条消息,并从消息队列中移除它(MSDN中文翻译上是错误,MSDN写的是不移除,而英文原文是移除),而实际结果也是移除的,如果你再运行一次客户端时,你会发现消息队列中只有一条消息,具体运行效果如下图所示:

MSMQ消息队列

五、总结

   到这里,MSMQ的内容就分享结束, 其MSMQ的实现原理也非常简单,一句话慨括就是服务器把消息放在一个公共的地方,这个地方叫做消息队列,而其他客户端可以从这个地方取出消息进行处理。

 

修改Oracle字符集

数据导入时报ORA-12899错误,即插入的数据长度超出字段的设置长度,实际长度并不长,这是由于Oracle字符集不同,汉字占的长度不同造成的。中文在ZHS16GBK中占2个字节,在UTF-8中却占3个字节,所以汉字导入UTF-8字符集的数据库就很容易出现字段长度不够,解决办法,一个是增加字段长度,还有就是修改字符集。

如果系统中已经存在很多数据,建议修改字段长度,因为修改字符集后原来数据库表中的汉字全部变成乱码。如果一定要修改字符集,必须先导出数据,待到字符集修改后再重新导入这些数据。

查看字符集的方法可以用PL/SQL DEVELOP —->Reports—->DBA—->NLS Database Parameters,结果如下图:

修改Oracle字符集

如上图所示,字符集是UTF-8,修改字符集的方法如下:

修改数据库字符集为:ZHS16GBK

开始->运行->cmd,输入sqlplus system/manager@orcl as SYSDBA
若此时数据库服务器已启动,则先执行 SHUTDOWN IMMEDIATE 命令关闭数据库服务器,
然后执行以下命令:
SQL>shutdown immediate
SQL>STARTUP MOUNT
SQL>ALTER SYSTEM ENABLE RESTRICTED SESSION;
SQL>ALTER SYSTEM SET JOB_QUEUE_PROCESSES=0;
SQL>ALTER SYSTEM SET AQ_TM_PROCESSES=0;
SQL>ALTER DATABASE OPEN;
SQL>ALTER DATABASE CHARACTER SET ZHS16GBK;
ERROR at line 1:ORA-12721: operation cannot execute when other sessions are active
若出现上面的错误,使用下面的办法进行修改,使用INTERNAL_USE可以跳过超集的检查:
SQL>ALTER DATABASE CHARACTER SET INTERNAL_USE ZHS16GBK;
SQL>SHUTDOWN IMMEDIATE
SQL>STARTUP

至此,字符集修改完毕,再查字符集,结果如下:

修改Oracle字符集

SQL Server数据库读写分离提高并发性

在一些大型的网站或者应用中,单台的SQL Server 服务器可能难以支撑非常大的访问压力。很多人在这时候,第一个想到的就是一个解决性能问题的利器——负载均衡。遗憾的是,SQL Server 的所有版本,包括2012年3月发布的SQL Server 2012,也未提供该功能。

扩展单台SQL Server 服务器,解决性能瓶颈,有两种方法:

一、分布式数据库。扩展和分布数据库到多台服务器,由多台服务器分布存储不同的数据,通过将数据和访问压力分布到多台服务器来解决性能瓶颈。以一个大型电子商务网站数据库为例,可以按照业务模块或功能模块,将数据分布到多台服务器存储。这种方法对程序改造难度较大,设计起来较为复杂,本文不作介绍。

SQL Server数据库读写分离提高并发性

二、读写分离。读写分离是中型规模应用的数据库系统常见设计方案,通过将数据从主服务器同步到其他SQL Server 服务器,提供非实时的查询功能,扩展性能并提高并发性。

SQL Server数据库读写分离提高并发性

数据库的读写分离的好处如下:

1.通过将“读”操作和“写”操作分离到不同的数据库服务器上,降低对主服务器的CPU、内存、存储、网络资源的争用;

2.主服务器的增删改进行时,不影响查询服务器的查询,降低阻塞的发生,提高了并发性;

3.在应用程序提交了报表请求、不合理的查询请求时,不会导致长时间的锁表;

4.建立容灾副本甚至实现异地容灾,在发生灾难时,可以减少数据的损失;

绝大部分的企业内部应用,可能不需要上图那么庞大的架构,一台主数据库服务器和一台查询服务器通常能满足读写分离的要求。而且应用程序调整起来非常方便:

1.在应用程序的配置文件中设置两个数据库连接字符串,一个指向主服务器,一个指向查询服务器;

2.增删改或者实时性查询使用指向主服务器的连接字符串;

3.允许非实时的查询及报表请求使用指向查询服务器的连接字符串。

那么主数据库服务器的数据如何同步到查询服务器上?同步的间隔又是怎样的?主服务器发生故障的时候,查询服务器能否接管用户的请求呢?有什么技术要求呢?

SQL Server 提供了三种技术,可以用于读写分离的实现:日志传送、事务复制和SQL 2012 中新增的功能Always On 技术。这三种技术的比较如下:

SQL Server数据库读写分离提高并发性

SQL Server 日志传送示意图

SQL Server数据库读写分离提高并发性

SQL Server 复制示意图

SQL Server数据库读写分离提高并发性

SQL Server Always On 示意图

SQL Server数据库读写分离提高并发性

静态方法与实例化方法区别

       静态可以认为是缓存,在软件启动的时候,就给静态成员分配了存储空间,在整个软件生命期内存在,直到系统退出才被垃圾回收器回收销毁。对不经常发生变化又使用频繁的东东,比如配置词语,可以使用静态的,减少和数据库的频繁交互、提升系统性能某些比较昂贵的资源,比如数据库连接对象,声明成静态完全没有必要,这是因为即使你声明成静态,连接也不会一直保持打开状态,徒增加系统开销。

      在性能方面会有差异,静态方法性能优于实例化方法,就是因为他不用实例化,程序开始运行的时候静态变量、静态方法就被分配了内存,所以你随时可以调用他,但这也是他的一个缺点,就是不会销毁。至于说什么时候该用静态方法,我认为程序调用频繁的处理过程可以包装成静态方法,譬如像一些自定义字符串格式化处理,数据类型转换,消息头的数据处理,一些算法处理过程等等,总之使用频率高你可以考虑包装成静态方法,不频繁使用的,你让他占着资源有什么意义呢。

消息队列MQ对比

1、ActiveMQ

是Apache下的一个子项目。 类似于ZeroMQ,它能够以代理人和点对点的技术实现队列。同时类似于RabbitMQ,它少量代码就可以高效地实现高级应用场景。RabbitMQ、ZeroMQ、ActiveMQ均支持常用的多种语言客户端 C++、Java、.Net,、Python、 PHP、 Ruby等。

2、RabbitMQ

是使用Erlang编写的一个开源的消息队列,本身支持很多的协议:AMQP,XMPP, SMTP, STOMP,也正是如此,使的它变的非常重量级,更适合于企业级的开发。同时实现了一个经纪人(Broker)构架,这意味着消息在发送给客户端时先在中心队列排队。对路由(Routing),负载均衡(Load balance)或者数据持久化都有很好的支持。

3、Redis

是一个Key-Value的NoSQL数据库,开发维护很活跃,虽然它是一个Key-Value数据库存储系统,但它本身支持MQ功能,所以完全可以当做一个轻量级的队列服务来使用。对于RabbitMQ和Redis的入队和出队操作,各执行100万次,每10万次记录一次执行时间。测试数据分为128Bytes、512Bytes、1K和10K四个不同大小的数据。实验表明:入队时,当数据比较小时redis的性能要高于RabbitMQ,而如果数据大小超过了10K,Redis则慢的无法忍受;出队时,无论数据大小,Redis都表现出非常好的性能,而RabbitMQ的出队性能则远低于Redis。

 

入队

出队

 

128B

512B

1K

10K

128B

512B

1K

10K

Redis

16088

15961

17094

25

15955

20449

18098

9355

RabbitMQ

10627

9916

9370

2366

3219

3174

2982

1588

4、ZeroMQ

号称最快的消息队列系统,尤其针对大吞吐量的需求场景。ZMQ能够实现RabbitMQ不擅长的高级/复杂的队列,但是开发人员需要自己组合多种技术框架,技术上的复杂度是对这MQ能够应用成功的挑战。ZeroMQ具有一个独特的非中间件的模式,你不需要安装和运行一个消息服务器或中间件,因为你的应用程序将扮演了这个服务角色。你只需要简单的引用ZeroMQ程序库,可以使用NuGet安装,然后你就可以愉快的在应用程序之间发送消息了。但是ZeroMQ仅提供非持久性的队列,也就是说如果down机,数据将会丢失。其中,Twitter的Storm中使用ZeroMQ作为数据流的传输。

5、Jafka/Kafka

Kafka是Apache下的一个子项目,是一个高性能跨语言分布式Publish/Subscribe消息队列系统,而Jafka是在Kafka之上孵化而来的,即Kafka的一个升级版。具有以下特性:快速持久化,可以在O(1)的系统开销下进行消息持久化;高吞吐,在一台普通的服务器上既可以达到10W/s的吞吐速率;完全的分布式系统,Broker、Producer、Consumer都原生自动支持分布式,自动实现复杂均衡;支持Hadoop数据并行加载,对于像hadoop的一样的日志数据和离线分析系统,但又要求实时处理的限制,这是一个可行的解决方案。Kafka通过Hadoop的并行加载机制来统一了在线和离线的消息处理,这一点也是本课题所研究系统所看重的。Apache Kafka相对于ActiveMQ是一个非常轻量级的消息系统,除了性能非常好之外,还是一个工作良好的分布式系统。

其他一些队列列表HornetQ、Apache Qpid、Sparrow、Starling、Kestrel、Beanstalkd、Amazon SQS就不再一一分析。