mysql 的一个sql查询的 物理读如何才能知道  (在oracle sqlsever可以轻松知道 判断io )这个应该需要知道的啦?

解决方案 »

  1.   

    使用SQL Profiler 性能分析器http://linux.chinaunix.net/techdoc/database/2009/07/21/1125239.shtml网上很多这样的帖子。
      

  2.   

    转下面的一篇, 但是还是没有看到逻辑读 物理读的 对应的选项??
    如下:
     -------------+------------+
    | (initialization) | 0.00000425 |
    | checking query cache for query | 0.00004050 |
    | checking permissions | 0.00001050 |
    | Opening tables | 0.00018250 |
    | System lock | 0.00000450 |
    | Table lock | 0.00001775 |
    | init | 0.00001075 |
    | optimizing | 0.00000550 |
    | executing | 0.00002775 |
    | end | 0.00000450 |
    | query end | 0.00000325 |
    | storing result in query cache | 0.00000400 |
    | freeing items | 0.00000400 |
    | closing tables | 0.00000500 |
    | logging slow query
    SQL优化] -- 如何使用SQL Profiler 性能分析器
    mysql 的 sql 性能分析器主要用途是显示 sql 执行的整个过程中各项资源的使用情况。分析器可以更好的展示出不良 SQL 的性能问题所在。
    下面我们举例介绍一下 MySQL SQL Profiler 的使用方法:
        * 首先,开启 MySQL SQL Profiler 
    mysql> SELECT @@profiling;
    +-------------+
    | @@profiling |
    +-------------+
    | 0 |
    +-------------+
    1 row in set (0.00 sec)
    mysql> SET profiling = 1;
    Query OK, 0 rows affected (0.00 sec)
    mysql> SELECT @@profiling;
    +-------------+
    | @@profiling |
    +-------------+
    | 1 |
    +-------------+
    1 row in set (0.00 sec)
    默认情况下 profiling 的值为 0 表示 MySQL SQL Profiler 处于 OFF 状态,开启 SQL 性能分析器后 profiling 的值为 1.
        * 通过 sql 性能分析器,我们来对比一下 下列语句前后 2 次执行过程的差异,对我们了解 sql 的详细执行过程是非常有帮助的。 
    mysql> create table t_engines select * from t_engines1;
    Query OK, 57344 rows affected (0.10 sec)
    Records: 57344 Duplicates: 0 Warnings: 0
    mysql> select count(*) from t_engines;
    +----------+
    | count(*) |
    +----------+
    | 57344 |
    +----------+
    1 row in set (0.00 sec)
    mysql> select count(*) from t_engines;
    +----------+
    | count(*) |
    +----------+
    | 57344 |
    +----------+
    1 row in set (0.00 sec)
    mysql> SHOW PROFILES;
    +----------+------------+-------------------------------------------------+
    | Query_ID | Duration | Query |
    +----------+------------+-------------------------------------------------+
    | 26 | 0.10213775 | create table t_engines select * from t_engines1 |
    | 27 | 0.00032775 | select count(*) from t_engines |
    | 28 | 0.00003850 | select count(*) from t_engines |
    +----------+------------+-------------------------------------------------+
    15 rows in set (0.01 sec)
    mysql> SHOW PROFILE FOR QUERY 27;
    +--------------------------------+------------+
    | Status | Duration |
    +--------------------------------+------------+
    | (initialization) | 0.00000425 |
    | checking query cache for query | 0.00004050 |
    | checking permissions | 0.00001050 |
    | Opening tables | 0.00018250 |
    | System lock | 0.00000450 |
    | Table lock | 0.00001775 |
    | init | 0.00001075 |
    | optimizing | 0.00000550 |
    | executing | 0.00002775 |
    | end | 0.00000450 |
    | query end | 0.00000325 |
    | storing result in query cache | 0.00000400 |
    | freeing items | 0.00000400 |
    | closing tables | 0.00000500 |
    | logging slow query | 0.00000300 |
    +--------------------------------+------------+
    15 rows in set (0.00 sec)
    mysql> SHOW PROFILE FOR QUERY 28;
    +-------------------------------------+------------+
    | Status | Duration |
    +-------------------------------------+------------+
    | (initialization) | 0.00000350 |
    | checking query cache for query | 0.00000750 |
    | checking privileges on cached query | 0.00000500 |
    | checking permissions | 0.00000525 |
    | sending cached result to client | 0.00001275 |
    | logging slow query | 0.00000450 |
    +-------------------------------------+------------+
    6 rows in set (0.00 sec)
    mysql> SELECT sum( FORMAT(DURATION, 6)) AS DURATION FROM INFORMATION_SCHEMA.PROFILING WHERE QUERY_ID =27 ORDER BY SEQ;
    +----------+
    | DURATION |
    +----------+
    | 0.000326 |
    +----------+
    1 row in set (0.00 sec)
    mysql> SELECT sum( FORMAT(DURATION, 6)) AS DURATION FROM INFORMATION_SCHEMA.PROFILING WHERE QUERY_ID =28 ORDER BY SEQ;
    +----------+
    | DURATION |
    +----------+
    | 0.000039 |
    +----------+
    1 row in set (0.00 sec)
    mysql>
    从上面的例子中我们可以清晰的看出 2 次执行 count 语句的差别, SHOW PROFILE FOR QUERY 27 展现的是第一次 count 统计的执行过程,包含了 Opening tables 、 Table lock 等操作 。而 SHOW PROFILE FOR QUERY 28 展示了第二次 count 统计的执行过程 , 第二次 count 直接从查询缓存中返回 count 统计结果,通过对比 2 次统计的总执行时间发现,缓存读的速度接近物理读的 10 倍。通过使用 SQL 性能分析器可以帮助我们对一些比较难以确定性能问题的 SQL 进行诊断,找出问题根源。
    本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u3/93470/showart_2002151.html
      

  3.   

    SHOW PROFILE ALL FOR QUERY 27;这样查看所有信息。里面有CPU,IO等。
      

  4.   

    1 判断是否有全表 索引
    2 物理读 逻辑读
    3 几个sql方式之间选择最少逻辑读的 sql。io上
    5 看子查询 等能否优化当你构建SQL语句时,按Ctrl+L就可以看到语句是如何执行,是用索引扫描还是表扫描? 通过SET STATISTICS IO ON 来查看逻辑读,完成同一功能的不同SQL语句,逻辑读 越小查询速度越快(当然不要找那个只有几百条记录的例子来反我)。重要:在我举的例子中,用的是聚集索引扫描,字段是字母加数字,大家可以试试看纯数字的、字母的、汉字的等等,了解下 MMSQL会如何改变SQL语句来利用索引。然后再试试非聚集索引是什么情况?用不用索引和什么有关?子查询MSSQL是如何执行?IN用不用索引,LIKE用不用索引?函数用不用索引?OR、AND、UNION?子查询呢?在这里我不一一去试给大家看了,只要知道了如何去看MSSQL的执行计划(图形和文本),很多事情就很明朗了。  大总结: 实现同一查询功能的SQL写法可能会有多种,如果判断哪种最优化,如果仅仅是从时间上来测,会受很多外界因素的影响,而我们明白了MSSQL如何去执行,通过IO逻辑读、通过查看图示的查询计划、通过其优化后而执行的SQL语句,才是优化SQL的真正途径。   另外提醒下:数据量的多少有时会影响MSSQL对同一种查询写法语句的执行计划,这一点在非聚集索引上特别明显,还有就是在多CPU与单CPU下,在多用户并发情况下,同一写法的查询语句执行计划会有所不同,这个就需要大家有机会去试验了(我也没有这方面的太多经验与大家分享)。   先写这些吧,由于我对MSSQL认识还很浅薄,如有不对的地方,还请指正。
    echo -
      

  5.   

    Microsoft® SQL Server™ 2000 有用于存储执行计划和数据缓冲区的内存池。池内分配给执行计划或数据缓冲区的百分比随系统状态动态波动。内存池中用于存储执行计划的部分称为过程高速缓存。 
    SQL Server 2000 执行计划包含下面两个主要组件: 
    ◆查询计划 执行计划的主体是一个重入的只读数据结构,可由任意数量的用户使用。这称为查询计划。查询计划中不存储用户环境。查询计划在内存中永远不会有一个或两个以上的复本:一个复本用于所有串行执行,一个复本用于所有并行执行。并行复本覆盖所有的并行执行,与并行执行的并行度无关。 
    ◆执行环境 每个正在执行查询的用户都有一个包含其执行专用数据(如参数值)的数据结构。该数据结构称为执行环境。执行环境数据结构可以重新使用。如果用户执行查询而其中的一个结构未使用,将会用新用户的环境重新初始化该结构。 
    在 SQL Server 2000 中执行任何 SQL 语句时,关系引擎将首先查看过程高速缓存中是否有用于同一 SQL 语句的现有执行计划。SQL Server 2000 重新使用所找到的任何现有计划以节省重新编译 SQL 语句的开销。如果没有现有执行计划,则 SQL Server 2000 将为查询生成新的执行计划。 
    SQL Server 2000 有一个高效的算法,可查找用于任何特定 SQL 语句的现有执行计划。在大多数系统中,这种扫描所使用的最小资源比通过重新使用现有计划而不是编译每个 SQL 语句所节省的资源要少。 
    该算法将新的 SQL 语句与高速缓存内现有的未用执行计划相匹配,并要求所有的对象引用完全合法。例如,这两个 SELECT 语句中的第一个语句与现有计划不匹配,而第二个语句则匹配: 
    SELECT * FROM Employees
    SELECT * FROM Northwind.dbo.Employees
     在 SQL Server 2000 实例中,个别执行计划重新使用的概率比在 SQL Server 6.5 或更早版本中高。 
    执行计划的老化 执行计划生成后便驻留在过程高速缓存中。只有当需要空间时,SQL Server 2000 才使旧的未用计划从高速缓存老化掉。每个查询计划和执行环境都有相关的成本因子,可表明编译结构所需的费用。这些数据结构还有一个年龄字段。对象每由连接引用一次,其年龄字段便按编译成本因子递增。例如,如果一个查询计划的成本因子是 8 且被引用了两次,它的年龄将变为 16。惰性写入器进程定期扫描过程高速缓存内的对象列表。惰性写入器减少每个对象的年龄字段,每扫描一次减少 1。在本例中,查询计划的年龄经过 16 次过程高速缓存扫描后减为 0,除非其他用户引用了该计划。如果满足下面三个条件,惰性写入器进程将释放对象: 
    内存管理器需要内存且所有可用内存都正在使用。 对象的年龄字段是 0。 对象在当前没有被连接引用。 因为每次引用对象时其年龄字段都会增加,所以经常被引用的对象的年龄字段不会减为 0,也不会从高速缓存老化掉。不经常被引用的对象将很快满足释放条件,但是不会真被释放,除非其它对象有内存需求。 剖析SQL Server执行计划
    (8)将鼠标移到图形执行计划上的表名(以及它的图标)上面,就会弹出一个窗口,从它上面可以看到一些信息。这些信息让你知道是否有用到索引来从表中获取数据,以及它是如何使用的。这些信息包括:(8.1)Table Scan(表扫描):如果看到这个信息,就说明数据表上没有聚集索引,或者查询优化器没有使用索引来查找。意即资料表的每一行都被检查到。如果资料表相对较小的话,表扫描可以非常快速,有时甚至快过使用索引。因此,当看到有执行表扫描时,第一件要做的事就是看看数据表有多少数据行。如果不是太多的话,那么表扫描可能提供了最好的总体效能。但如果数据表大的话,表扫描就极可能需要长时间来完成,查询效能就大受影响。在这种情况下,就需要仔细研究,为数据表增加一个适当的索引用于这个查询。假设你发现某查询使用了表扫描,有一个合适的非聚集索引,但它没有用到。这意味着什么呢?为什么这个索引没有用到呢?如果需要获得的数据量相对数据表大小来说非常大,或者数据选择性不高(意味着同一个字段中重复的值很多),表扫描经常会比索引扫描快。例如,如果一个数据表有10000个数据行,查询返回1000行,如果这个表没有聚集索引的话,那么表扫描将比使用一个非聚集索引更快。或者如果数据表有10000个数据行,且同一个字段(WHERE条件句有用到这个字段)上有1000笔重复的数据,表扫描也会比使用非聚集索引更快。查看图形执行计划上的数据表上的弹出式窗口时,请注意”预估的资料行数(Estimated Row Count)”。这个数字是查询优化器作出的多少个数据行会被返回的最佳推测。如果执行了表扫描且”预估的数据行数”数值很高的话,就意味着返回的记录数很多,查询优化器认为执行表扫描比使用可用的非聚集索引更快(8.2)Index Seek(索引查找):索引查找意味着查询优化器使用了数据表上的非聚集索引来查找数据。性能通常会很快,尤其是当只有少数的数据行被返回时(8.3)Clustered Index Seek(聚集索引查找):这指查询优化器使用了数据表上的聚集索引来查找数据,性能很快。实际上,这是SQL Server能做的最快的索引查找类型(8.4)Clustered Index Scan(聚集索引扫描):聚集索引扫描与表扫描相似,不同的是聚集索引扫描是在一个建有聚集索引的数据表上执行的。和一般的表扫描一样,聚集索引扫描可能表明存在效能问题。一般来说,有两种原因会引此聚集索引扫描的执行。第一个原因,相对于数据表上的整体数据行数目,可能需要获取太多的数据行。查看”预估的数据行数量(Estimated Row Count)”可以对此加以验证。第二个原因,可能是由于WHERE条件句中用到的字段选择性不高。在任何情况下,与标准的表扫描不同,聚集索引扫描并不会总是去查找数据表中的所有数据,所以聚集索引扫描一般都会比标准的表扫描要快。通常来说,要将聚集索引扫描改成聚集索引查找,你唯一能做的是重写查询语句,让语句限制性更多,从而返回更少的数据行(9)绝大多数情况下,查询优化器会对连接进行分析,按最有效率的顺序,使用最有效率的连接类型来对数据表进行连接。但并不总是如此。在图形执行计划中你可以看到代表查询所使用到的各种不同连接类型的图标。此外,每个连接图标都有两个箭头指向它。指向连接图标的上面的箭头代表该连接的外部表,下面的箭头则代表这个连接的内部表。箭头的另一头则指向被连接的数据表名。有时在多表连接的查询中,箭头的另一头指向的并不是一个数据表,而是另一个连接。如果将鼠标移到指向外部连接与内部连接的箭头上,就可以看到一个弹出式窗口,告诉你有多少数据行被发送至这个连接来进行处理。外部表应该总是比内部表含有更少的数据行。如果不是,则说明查询优化器所选择的连接顺序可能不正确(10) 查看图形执行计划时,你可能会发现某个图标的文字用红色显示,而非通常情况下的黑色。这意味着相关的表的一些统计数据遗失,统计数据是查询优化器生成一个好的执行计划所必须的,
    遗失的统计数据可以通过右键这个图标,并选择”创建遗失的统计资料”来创建。这时会弹出”创建遗失的统计数据”对话框,通过它可以很容易地创建遗失的统计数据。
    当可以选择去更新遗失的统计资料时,应该总是这样做,因为这样极有可能让你正在分析的查询语句从中获得效能上的好处
    (11) 有时你会在图形执行计划上看到标识了”Assert”的图标。这意味着查询优化器正在验证查询语句是否有违反引用完整性或者条件约束。如果没有,则没有问题。但如果有的话,查询优化器将无法为该查询建立执行计划,同时会产生一个错误
    (12) 你常常会在图形执行计划上看到标识成”书签查找(Book Lookup)”的图标。书签查找相当常见。书签查找的本质是告诉你查询处理器必须从数据表或者聚集索引中来查找它所需要的数据行,而不是从非聚集索引中直接读取。
    打比方说,如果一个查询语句的SELECT,JOIN以及WHERE子句中的所有字段,都不存在于那个用来定位符合查询条件的数据行的非聚集索引中,那么查询优化器就不得不做额外的工作在数据表或聚集索引中查找那些满足这个查询语句的字段。另一种引起书签查找的原因是使用了SELECT *。由于在绝大多情况下它会返回比你实际所需更多的数据,所以应该永不使用SELECT *.
    从性能方面来说,书签查找是不理想的。因为它会请求额外的I/O开销在字段中查找以返回所需的数据行。
    如果认为书签查找防碍了查询的性能,那么有四种选择可以用来避免它:可以建立WHERE子句会用到的聚集索引,利用索引交集的优势,建立覆盖的非聚集索引,或者(如果是SQL Server 2000/2005企业版的话)可以建立索引视图。如果这些都不可能,或者使用它们中的任何一个都会耗用比书签查找更多的资源,那么书签查找就是最佳的选择了。(13) 有时查询优化器需要在tempdb数据库中建立临时工作表。如果是这样的话,就意味着图形执行计划中有标识成Index Spool, Row Count Spool或者Table Spool的图标。
    任何时候,使用到工作表一般都会防碍到性能,因为需要额外的I/O开销来维护这个工作表。理想情况下应该不要用到工作表。不幸的是并不能总是避免用到工作表。有时当使用工作表比其它选择更有效率时,它的使用实际上会增强性能。不论何种情况,图形执行计划中的工作表都应该引起你的警觉。应该仔细检查这样的查询语句,看看是否有办法重写查询来避免用到工作表。有可能没有办法。但如果有的话,你就朝提升这个查询的性能方面前进了一步.
    (14) 在图形执行计划上看到流聚合(Stream Aggregate)图标就意味着有对一个单一的输入进行了聚合。当使用了DISTINCT子句,或者任何聚合函数时,如AVG, COUNT, MAX, MIN,或者SUM等,流聚合操作就相当常见。(15)查询分析器与Management Studio不是唯一的可以生成、显示查询执行计划的工具。SQL Server Profiler也可以显示执行计划,但格式是文本形式的。使用SQL Server Profiler来显示执行计划的一个优势是,它能为实际运行的大量查询产生执行计划。如果使用查询分析器和Management Studio,则一次只能运行一个(16)如果在查询中使用了OPTION FAST提示,那就必须小心执行计划的结果可能不是你所期望的。这时你所看到的执行计划基于使用了FAST提示的结果,而不是整个查询语句的实际执行计划。FAST提示用来告知果询优化器尽可能快地返回指定行数的数据行,即便这样做会防碍查询的整体性能。使用这个提示的目的在于为使用者快速返回特定行数的记录,由此让他们产生速度非常快速的错觉。。当返回指定行数的数据行后,剩余的数据行按照它们通常的速度返回。
    因此,如果使用了FAST提示,那么生成的执行计划只是基于那些FAST返回的数据行,而非查询要返回的所有数据行。如果想看所有数据行的执行计划,那么就必须移除这个FAST提示.
     
      

  6.   

    sp_executesql的运用       MSSQL为我们提供了两种动态执行SQL语句的命令,分别是EXEC和sp_executesql;通常,sp_executesql则更具有优势,它提供了输入输出接口,而EXEC没有。还有一个最大的优点就是运用 sp_executesql,能够重用执行计划,这就大大提供了执行性能(对于这个我在后面的例子中会详加说明),还可以编写更安全的代码  我们可以看到,每执行一次都要产生一次的编译,执行计划没有得到充分重用。EXEC除了不支持动态批处理中的输入参数外,他也不支持输出参数。默认情况下,EXEC把查询的输出返回给调用者。例如下面代码返回Orders表中所有的记录数DECLARE @sql NVARCHAR(MAX) SET @sql = 'SELECT COUNT(ORDERID) FROM Orders'; EXEC(@sql); 然而,如果你要把输出返回给调用批处理中的变量,事情就没有那么基本了。为此,你必须运用 INSERT EXEC语法把输出插入到一个目标表中,然后从这表中获取值后赋给该变量,就像这样:
    DECLARE @sql NVARCHAR(MAX),@RecordCount INT SET @sql = 'SELECT COUNT(ORDERID) FROM Orders';   CREATE TABLE #T(TID INT); INSERT INTO #T EXEC(@sql); SET @RecordCount = (SELECT TID FROM #T) SELECT @RecordCount DROP TABLE #T 2,sp_executesql的运用sp_executesql命令在SQL Server中引入的比EXEC命令晚一些,它主要为重用执行计划提供更好的支持。为了和EXEC作一个鲜明的比较 ,我们看看如果用代码1的代码,把EXEC换成sp_executesql,看看能不能得到我们所期望的结果DECLARE @TableName VARCHAR(50),@sql NVARCHAR(MAX),@OrderID INT ,@sql2 NVARCHAR(MAX); SET @TableName = 'Orders '; SET @OrderID = 10251; SET @sql = 'SELECT * FROM '+QUOTENAME(@TableName) + ' WHERE OrderID = '+CAST(@OrderID AS VARCHAR(50)) + ' ORDER BY ORDERID DESC' EXEC sp_executesql @sql 留心最后一行;事实证明可以运行;sp_executesql提供接口sp_executesql命令比EXEC命令更灵活,因为它提供一个接口,该接口及支持输入参数也支持输出参数。这功能使你可以建立带参数的查询字符串,这样就可以比EXEC更好的重用执行计划,sp_executesql的构成与存储流程非常相似,不同之处在于你是动态构建代码。它的构成包括:代码快,参数声明部分,参数赋值部分。说了这么多,还是看看它的语法吧EXEC sp_executesql@stmt = <statement>,--类似存储流程主体@params = <params>, --类似存储流程参数部分<params assignment> --类似存储流程调用@stmt参数是输入的动态批处理,它可以引入输入参数或输出参数,和存储流程的主体语句一样,只不过它是动态的,而存储流程是静态的,不过你也可以在存储流程中运用 sp_executesql;@params参数与定义输入/输出参数的存储流程头类似,实际上和存储流程头的语法完全一样;@<params assignment> 与调用存储流程的EXEC部分类似。为了说明sp_executesql对执行计划的管理优于EXEC,我将运用前面讨论EXEC时用到的代码。 1: DECLARE @TableName VARCHAR(50),@sql NVARCHAR(MAX),@OrderID INT;  2: SET @TableName = 'Orders ';  3: SET @OrderID = 10251;  4: SET @sql = 'SELECT * FROM '+QUOTENAME(@TableName) + ' WHERE OrderID = @OID ORDER BY ORDERID DESC'  5: EXEC sp_executesql  6: @stmt = @sql,  7: @params = N'@OID AS INT ',  8: @OID = @OrderID 在调用该代码和检查它生成的执行计划前,先清空缓存中的执行计划;DBCC FREEPROCCACHE将上面的动态代码执行3次,每次执行都赋予@OrderID 不同的值,然后查询sys.syscacheobjects表,并留心它的输出,优化器只建立了一个备用计划,而且该计划被重用的3次SELECT cacheobjtype,objtype,usecounts,sql FROM sys.syscacheobjects WHERE sql NOT LIKE '%cache%' AND sql NOT LIKE '%sys.%' AND sql NOT LIKE '%sp_executesql%' 点击F5运行,就会出现如下表所示的结果;sq_executesql的另一个与其接口有关的强大功能是,你可以运用输出参数为调用批处理中的变量返回值。运用 该功能可以防止用临时表返回数据,从而得到更高效的代码和更少的重新编译。定义和运用输出参数的语法与存储流程类似。也就是说,你须要在声明参数时指定OUTPUT子句。例如,下面的静态代码基本的演示了如何 从动态批处理中运用 输出参数@p把值返回到外部批处理中的变量@i.DECLARE @sql AS NVARCHAR(12),@i AS INT;SET @sql = N' SET @p = 10'; EXEC sp_executesql @stmt = @sql, @params = N'@p AS INT OUTPUT',  @p = @i OUTPUTSELECT @i该代码返回输出10
     
              以上就是EXEC和sp_executesql的主要区别,如果各位看官觉得哪不对或者表达不清楚的,还请多多指出^_^http://www.yqdown.com/shujuku/SQL-Server/4330_3.htm
    SQLSERVER 动态执行SQL sp_executesql与EXEC
    摘自SQL server帮助文档
    对大家优查询速度有帮助!建议使用 sp_executesql 而不要使用 EXECUTE 语句执行字符串。支持参数替换不仅使 sp_executesql 比 EXECUTE 更通用,而且还使 sp_executesql 更有效,因为它生成的执行计划更有可能被 SQL Server 重新使用。
    自包含批处理sp_executesql 或 EXECUTE 语句执行字符串时,字符串被作为其自包含批处理执行。SQL Server 将Transact-SQL 语句或字符串中的语句编译进一个执行计划,该执行计划独立于包含 sp_executesql 或 EXECUTE 语句的批处理的执行计划。下列规则适用于自含的批处理:    * 直到执行 sp_executesql 或EXECUTE 语句时才将sp_executesql 或 EXECUTE 字符串中的 Transact-SQL 语句编译进执行计划。执行字符串时才开始分析或检查其错误。执行时才对字符串中引用的名称进行解析。    * 执行的字符串中的 Transact-SQL 语句,不能访问 sp_executesql 或 EXECUTE 语句所在批处理中声明的任何变量。包含 sp_executesql 或 EXECUTE 语句的批处理不能访问执行的字符串中定义的变量或局部游标。    * 如果执行字符串有更改数据库上下文的 USE 语句,则对数据库上下文的更改仅持续到 sp_executesql 或 EXECUTE 语句完成。通过执行下列两个批处理来举例说明:/* Show not having access to variables from the calling batch. */
    DECLARE @CharVariable CHAR(3)
    SET @CharVariable = 'abc'
    /* sp_executesql fails because @CharVariable has gone out of scope. */
    sp_executesql N'PRINT @CharVariable'
    GO/* Show database context resetting after sp_executesql completes. */
    USE pubs
    GO
    sp_executesql N'USE Northwind'
    GO
    /* This statement fails because the database context
       has now returned to pubs. */
    SELECT * FROM Shippers
    GO替换参数值sp_executesql 支持对 Transact-SQL 字符串中指定的任何参数的参数值进行替换,但是 EXECUTE 语句不支持。因此,由 sp_executesql 生成的 Transact-SQL 字符串比由 EXECUTE 语句所生成的更相似。SQL Server 查询优化器可能将来自 sp_executesql 的 Transact-SQL 语句与以前所执行的语句的执行计划相匹配,以节约编译新的执行计划的开销。使用 EXECUTE 语句时,必须将所有参数值转换为字符或 Unicode 并使其成为 Transact-SQL 字符串的一部分:DECLARE @IntVariable INT
    DECLARE @SQLString NVARCHAR(500)
    /* Build and execute a string with one parameter value. */
    SET @IntVariable = 35
    SET @SQLString = N'SELECT * FROM pubs.dbo.employee WHERE job_lvl = ' +
                     CAST(@IntVariable AS NVARCHAR(10))
    EXEC(@SQLString)
    /* Build and execute a string with a second parameter value. */
    SET @IntVariable = 201
    SET @SQLString = N'SELECT * FROM pubs.dbo.employee WHERE job_lvl = ' +
                     CAST(@IntVariable AS NVARCHAR(10))
    EXEC(@SQLString)如果语句重复执行,则即使仅有的区别是为参数所提供的值不同,每次执行时也必须生成全新的 Transact-SQL 字符串。从而在下面几个方面产生额外的开销:    * SQL Server 查询优化器具有将新的 Transact-SQL 字符串与现有的执行计划匹配的能力,此能力被字符串文本中不断更改的参数值妨碍,特别是在复杂的 Transact-SQL 语句中。    * 每次执行时均必须重新生成整个字符串。    * 每次执行时必须将参数值(不是字符或 Unicode 值)投影到字符或 Unicode 格式。sp_executesql 支持与 Transact-SQL 字符串相独立的参数值的设置:DECLARE @IntVariable INT
    DECLARE @SQLString NVARCHAR(500)
    DECLARE @ParmDefinition NVARCHAR(500)/* Build the SQL string once. */
    SET @SQLString =
         N'SELECT * FROM pubs.dbo.employee WHERE job_lvl = @level'
    /* Specify the parameter format once. */
    SET @ParmDefinition = N'@level tinyint'/* Execute the string with the first parameter value. */
    SET @IntVariable = 35
    EXECUTE sp_executesql @SQLString, @ParmDefinition,
                          @level = @IntVariable
    /* Execute the same string with the second parameter value. */
    SET @IntVariable = 32
    EXECUTE sp_executesql @SQLString, @ParmDefinition,
                          @level = @IntVariable此 sp_executesql 示例完成的任务与前面的 EXECUTE 示例所完成的相同,但有下列额外优点:    * 因为 Transact-SQL 语句的实际文本在两次执行之间未改变,所以查询优化器应该能将第二次执行中的 Transact-SQL 语句与第一次执行时生成的执行计划匹配。这样,SQL Server 不必编译第二条语句。    * Transact-SQL 字符串只生成一次。    * 整型参数按其本身格式指定。不需要转换为 Unicode。说明  为了使 SQL Server 重新使用执行计划,语句字符串中的对象名称必须完全符合要求。重新使用执行计划在 SQL Server 早期的版本中要重新使用执行计划的唯一方式是,将 Transact-SQL 语句定义为存储过程然后使应用程序执行此存储过程。这就产生了管理应用程序的额外开销。使用 sp_executesql 有助于减少此开销,并使 SQL Server 得以重新使用执行计划。当要多次执行某个 Transact-SQL 语句,且唯一的变化是提供给该 Transact-SQL 语句的参数值时,可以使用 sp_executesql 来代替存储过程。因为 Transact-SQL 语句本身保持不变仅参数值变化,所以 SQL Server 查询优化器可能重复使用首次执行时所生成的执行计划。下例为服务器上除四个系统数据库之外的每个数据库生成并执行 DBCC CHECKDB 语句:USE master
    GO
    SET NOCOUNT ON
    GO
    DECLARE AllDatabases CURSOR FOR
    SELECT name FROM sysdatabases WHERE dbid > 4OPEN AllDatabasesDECLARE @DBNameVar NVARCHAR(128)
    DECLARE @Statement NVARCHAR(300)FETCH NEXT FROM AllDatabases INTO @DBNameVar
    WHILE (@@FETCH_STATUS = 0)
    BEGIN
       PRINT N'CHECKING DATABASE ' + @DBNameVar
       SET @Statement = N'USE ' + @DBNameVar + CHAR(13)
          + N'DBCC CHECKDB (' + @DBNameVar + N')'
       EXEC sp_executesql @Statement
       PRINT CHAR(13) + CHAR(13)
       FETCH NEXT FROM AllDatabases INTO @DBNameVar
    ENDCLOSE AllDatabases
    DEALLOCATE AllDatabases
    GO
    SET NOCOUNT OFF
    GO当目前所执行的 Transact-SQL 语句包含绑定参数标记时,SQL Server ODBC 驱动程序使用 sp_executesql 完成 SQLExecDirect。但例外情况是 sp_executesql 不用于执行中的数据参数。这使得使用标准 ODBC 函数或使用在 ODBC 上定义的 API(如 RDO)的应用程序得以利用 sp_executesql 所提供的优势。定位于 SQL Server 2000 的现有的 ODBC 应用程序不需要重写就可以自动获得性能增益。有关更多信息,请参见使用语句参数。用于 SQL Server 的 Microsoft OLE DB 提供程序也使用 sp_executesql 直接执行带有绑定参数的语句。使用 OLE DB 或 ADO 的应用程序不必重写就可以获得 sp_executesql 所提供的优势。 http://www.cnblogs.com/edobnet/archive/2004/11/10/62155.html
      

  7.   

    咋回事,说着说着变成MSSQL了
      

  8.   

    没有办法 同时做2个db (  不同类型的db)的dba 。反正无论什么db,原理都是相同的
    sqlserver 不同于 mysqlasp.net+sqlserver 是无缝连接  ado.net+存储过程很强的
    但java +mysql(他的存储过程 不好说)   
      

  9.   

    检查这些状态就知道了。mysql> show status like '%read%';
    +-----------------------------------+---------+
    | Variable_name                     | Value   |
    +-----------------------------------+---------+
    | Com_ha_read                       | 0       |
    | Delayed_insert_threads            | 0       |
    | Handler_read_first                | 0       |
    | Handler_read_key                  | 0       |
    | Handler_read_next                 | 0       |
    | Handler_read_prev                 | 0       |
    | Handler_read_rnd                  | 0       |
    | Handler_read_rnd_next             | 46      |
    | Innodb_buffer_pool_read_ahead_rnd | 1       |
    | Innodb_buffer_pool_read_ahead_seq | 0       |
    | Innodb_buffer_pool_read_requests  | 555     |
    | Innodb_buffer_pool_reads          | 15      |
    | Innodb_data_pending_reads         | 0       |
    | Innodb_data_read                  | 2969600 |
    | Innodb_data_reads                 | 58      |
    | Innodb_pages_read                 | 22      |
    | Innodb_rows_read                  | 0       |
    | Key_read_requests                 | 0       |
    | Key_reads                         | 0       |
    | Slow_launch_threads               | 0       |
    | Threads_cached                    | 0       |
    | Threads_connected                 | 1       |
    | Threads_created                   | 1       |
    | Threads_running                   | 1       |
    +-----------------------------------+---------+
    24 rows in set (0.01 sec)mysql>