搜索
首页数据库mysql教程调整SQLSERVER非最优执行计划

我们发出的 SQL 语句,如果没有对应的缓存,优化器都会创建一个相应的 执行 计划 。但是,优化器基于成本的优化过程,在面对比较复杂的 SQL 语句时,不会考虑所有的情况。因此有些时候,就会给出一个近似高效的 执行 计划 。同时,受生产环境负载的影响,可

    我们发出的SQL语句,如果没有对应的缓存,优化器都会创建一个相应的执行计划。但是,优化器基于成本的优化过程,在面对比较复杂的SQL语句时,不会考虑所有的情况。因此有些时候,就会给出一个近似高效的执行计划。同时,受生产环境负载的影响,可能优化的过程会更不彻底,因此我们就应该控制语句的复杂程度,以减少优化器考虑各种组合的可能性。

当系统的性能出现问题时,即便你的索引建的很完美,但有的时候因为选择度的问题,你还要考虑怎么样在选择度不高的时候避免对表的扫描。防止像在高速公路塞车一样,所有的查询都要等待再等待,就像公交车一样。虽然SQL2005中有INCLUDE的功能,打破了在建立非聚集索引时16个字段900个字节的限制。但包含过多的INCLUE字段的代价是浪费太多的磁盘空间。当然,我们可能不在乎磁盘空间开销,毕竟是客户买单。面对如此大的索引数据量,SQL2005也增加了备份的策略。用文件或文件组的方式来处理。但多文件或文件组的备份是基于多个备份基准的,因此给管理带来了一定的挑战性。所以,我们应该首先考虑好用既有的索引来优化查询。实在没有办法时才去考虑新建索引或调整索引的字段。没有最好的,只有追求一个更合适的索引,尽量减少创建太多的索引。因为这会给数据的修改造成负担。

在进行语句级的调优时,我们首先要明确一下调优的目的是什么。在有了合适的索引时,就是如何有效的利用它们在CPU、内存、I/O之间达到一个平衡。如果你的内存一直很紧张,我们就想办法避免那些占用太多内存的运算符的使用。每个运算符在特定的场合使用是很高效的,没有什么是一成不变的。只有我们多试,才能找到一个最佳的平衡点。

下面我们通过一个示例来演示一下对一个SQLSERVER生成的不是很高效的执行计划调整方法。调整前后的成本开销为9:1,这样就能提高系统的并发操作。

调整SQLSERVER非最优执行计划 

调整SQLSERVER非最优执行计划调整SQLSERVER非最优执行计划Code
调整SQLSERVER非最优执行计划SELECT P.Name,P.Color,PSC.Name AS SubcategoryName,PC.Name AS CategoryName,
调整SQLSERVER非最优执行计划    S.SalesOrderID,S.OrderDate,OD.LineTotal
调整SQLSERVER非最优执行计划    
FROM Production.Product P
调整SQLSERVER非最优执行计划    
JOIN Production.ProductSubcategory PSC
调整SQLSERVER非最优执行计划        
ON P.ProductSubcategoryID = PSC.ProductSubcategoryID
调整SQLSERVER非最优执行计划    
JOIN Production.ProductCategory PC
调整SQLSERVER非最优执行计划        
ON PSC.ProductCategoryID = PC.ProductCategoryID
调整SQLSERVER非最优执行计划    
JOIN Sales.SalesOrderDetail OD
调整SQLSERVER非最优执行计划        
ON OD.ProductID = P.ProductID
调整SQLSERVER非最优执行计划    
JOIN Sales.SalesOrderHeader S
调整SQLSERVER非最优执行计划        
ON OD.SalesOrderID = S.SalesOrderID
调整SQLSERVER非最优执行计划
WHERE S.SalesPersonID = 275 AND PSC.Name = N'Road Bikes'

 这个查询要查出某个销售人员的某个子类产品的销售情况及相关的产品的信息。我们知道该销售人员的所有销售产品中只有一部分会属于某一类的产品。因此,最终要查询的结果是下面两者的交集部分。随着两者交集部分的变化,SQLSERVER给出的总体的查询思路没有多大变化,因此我们应该进行干涉了。

调整SQLSERVER非最优执行计划 

下面是SQLSERVER为我们生成的执行计划

调整SQLSERVER非最优执行计划

部分图形计划显示如下:

调整SQLSERVER非最优执行计划

大家看到计划中对Sales.SalesOrderHeader表进行了一次扫描,而这张表是一个增长很快的表,所以对这样的表进行扫描是一种很耗时的查询。扫描是因为查询中有OrderDate,而这个字段没有索引。所以只有在聚集索引的叶级,也就是真正的数据页上才能获得此信息。同时,Sales.SalesOrderDetail中对应了很多订单明细项,这也是增长很快的表。这里的聚集索引查找是因为要查询LineTotal,这是个计算字段,上面同样也没建立索引。为了计算这个值,会消耗很多的CPU资源。

    我们知道查询中联接产品和订单的表是Sales.SalesOrderDetail,如果我们能通过唯有的两个查询条件先在索引级别中把两者的交集取出来,最终再去查询只在数据页级存在的数据就会减少很多的资源浪费。下面是调整后的查询过程:

  1. 用于保存销售人员销售的产品和该类产品的交集部分的表变量,此处使用表变量可以防止在过程中引起重新编译。http://www.cnblogs.com/tom-fu/archive/2008/03/09/1096993.html

    调整SQLSERVER非最优执行计划调整SQLSERVER非最优执行计划Code
    DECLARE @udt_sales TABLE
    (
        SalesOrderID          
    INT NOT NULL,
        SalesOrderDetailID    
    INT NOT NULL
    )

  2. 用于保存某类产品相关信息的表变量

    调整SQLSERVER非最优执行计划调整SQLSERVER非最优执行计划Code
    DECLARE @udt_products TABLE
    (
        ProductID            
    INT    NOT NULL,
        
    [Name]              [Name] NOT NULL,
        Color               
    nvarchar(15NULL,
        SubcategoryName    
    [Name] NOT NULL
        CategoryName        
    [Name] NOT NULL
    )    

  3. 因为Sales.SalesOrderHeader在SalesPersonID字段有非聚集索引,所以查询275的订单可直接在此索引中查找。同时,我们看到在Sales.SalesOrderDetail表的ProductID字段建了一个非聚集索引,而SalesOrderID,SalesOrderDetailID作为聚集索引是该索引的键值字段。所以只在这个非聚集索引中即可查询到SalesOrderIDSalesOrderDetailID,从而减少I/O的操作。执行过程如下图所示

    调整SQLSERVER非最优执行计划调整SQLSERVER非最优执行计划Code
    INSERT INTO @udt_sales
    SELECT OD.SalesOrderID,OD.SalesOrderDetailID 
    FROM Sales.SalesOrderHeader S
        
    JOIN Sales.SalesOrderDetail OD 
            
    ON OD.SalesOrderID = S.SalesOrderID AND S.SalesPersonID = 275 
        
    JOIN (Production.ProductSubcategory PSC
                
    JOIN Production.Product P    
                    
    ON P.ProductSubcategoryID = PSC.ProductSubcategoryID AND PSC.Name = N'Road Bikes')
           
    ON P.ProductID=OD.ProductID

调整SQLSERVER非最优执行计划

  1. 把产品相关的信息存于表变量中以避免在联接中多次查询这些表

    调整SQLSERVER非最优执行计划调整SQLSERVER非最优执行计划Code
    调整SQLSERVER非最优执行计划INSERT INTO @udt_products
    调整SQLSERVER非最优执行计划
    SELECT P.ProductID,P.Name,P.Color,PSC.Name,PC.Name
    调整SQLSERVER非最优执行计划
    FROM Production.Product P    
    调整SQLSERVER非最优执行计划        
    JOIN Production.ProductSubcategory PSC
    调整SQLSERVER非最优执行计划            
    ON P.ProductSubcategoryID = PSC.ProductSubcategoryID
    调整SQLSERVER非最优执行计划        
    JOIN Production.ProductCategory PC
    调整SQLSERVER非最优执行计划            
    ON PSC.ProductCategoryID = PC.ProductCategoryID
    调整SQLSERVER非最优执行计划
    WHERE PSC.Name = N'Road Bikes'

  2. 最终用取得的交集部分和订单及明细表联接,查询出S.OrderDate,OD.LineTotal。因为这时是用取得的较小的交集部分来查询,所以避免了对Sales.SalesOrderHeader的表扫描。

    调整SQLSERVER非最优执行计划调整SQLSERVER非最优执行计划Code
    调整SQLSERVER非最优执行计划SELECT UP.Name,UP.Color,UP.SubcategoryName,UP.CategoryName,
    调整SQLSERVER非最优执行计划        S.SalesOrderID,S.OrderDate,OD.LineTotal
    调整SQLSERVER非最优执行计划
    FROM @udt_sales US
    调整SQLSERVER非最优执行计划        
    INNER JOIN Sales.SalesOrderHeader S
    调整SQLSERVER非最优执行计划            
    ON US.SalesOrderID=S.SalesOrderID
    调整SQLSERVER非最优执行计划        
    JOIN Sales.SalesOrderDetail OD 
    调整SQLSERVER非最优执行计划            
    ON US.SalesOrderID=OD.SalesOrderID AND US.SalesOrderDetailID=OD.SalesOrderDetailID
    调整SQLSERVER非最优执行计划        
    JOIN @udt_products UP
    调整SQLSERVER非最优执行计划            
    ON OD.ProductID=UP.ProductID

     成本的开销大,不一定代表执行时间就慢。如果你在机器上执行,因为受语句执行时机器的资源使用情况,所以不能只单纯依靠执行时间来判断,如果你追求更快的速度可以想办法把它改成并行的方式,这时就会降低系统的并发性。当然如果在不影响并发性的情况下,SQLSERVER也会主动的选择使用并发的方式。把优化前后的语句分别一前一后的去执行,你会得到不同的执行时间。所以最终还是要看I/O和里面所包含的各个运算符的操作。同时,如果你的查询能占用更少的资源,则能提高系统的并发性。这样在总体上来讲,你的系统性能还是会提高一些。

    当然,如果再结合一些提示的使用可能还有更高效的查询方法,或是再调整一下执行的逻辑。同时,我所举的示例只是在查询条件的选择度不高时的情况,如果查询条件选择度很高的话,SQLSERVER执行的整个过程也不会和现在的这个样。INSERT INTO本身也是个耗能大户,如果相比有太多的数据时就不太合适了。大家可以自己试一下。丢车保帅,不同的查询条件两者的开销也会发生变化。我们唯有做好最坏的打算,防止因为选择度的变化造成的这种性能开销。基本的原则就是避免对增长很快的大表扫描,分解复杂的查询以减少优化器优化时考虑各种组合的可能性。因为它并不清楚你查询的逻辑到底是怎么样的。最终的执行结果如下。

调整SQLSERVER非最优执行计划

声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
说明InnoDB重做日志和撤消日志的作用。说明InnoDB重做日志和撤消日志的作用。Apr 15, 2025 am 12:16 AM

InnoDB使用redologs和undologs确保数据一致性和可靠性。1.redologs记录数据页修改,确保崩溃恢复和事务持久性。2.undologs记录数据原始值,支持事务回滚和MVCC。

在解释输出(类型,键,行,额外)中要查找的关键指标是什么?在解释输出(类型,键,行,额外)中要查找的关键指标是什么?Apr 15, 2025 am 12:15 AM

EXPLAIN命令的关键指标包括type、key、rows和Extra。1)type反映查询的访问类型,值越高效率越高,如const优于ALL。2)key显示使用的索引,NULL表示无索引。3)rows预估扫描行数,影响查询性能。4)Extra提供额外信息,如Usingfilesort提示需要优化。

在解释中使用临时状态以及如何避免它是什么?在解释中使用临时状态以及如何避免它是什么?Apr 15, 2025 am 12:14 AM

Usingtemporary在MySQL查询中表示需要创建临时表,常见于使用DISTINCT、GROUPBY或非索引列的ORDERBY。可以通过优化索引和重写查询避免其出现,提升查询性能。具体来说,Usingtemporary出现在EXPLAIN输出中时,意味着MySQL需要创建临时表来处理查询。这通常发生在以下情况:1)使用DISTINCT或GROUPBY时进行去重或分组;2)ORDERBY包含非索引列时进行排序;3)使用复杂的子查询或联接操作。优化方法包括:1)为ORDERBY和GROUPB

描述不同的SQL交易隔离级别(读取未读取,读取,可重复的读取,可序列化)及其在MySQL/InnoDB中的含义。描述不同的SQL交易隔离级别(读取未读取,读取,可重复的读取,可序列化)及其在MySQL/InnoDB中的含义。Apr 15, 2025 am 12:11 AM

MySQL/InnoDB支持四种事务隔离级别:ReadUncommitted、ReadCommitted、RepeatableRead和Serializable。1.ReadUncommitted允许读取未提交数据,可能导致脏读。2.ReadCommitted避免脏读,但可能发生不可重复读。3.RepeatableRead是默认级别,避免脏读和不可重复读,但可能发生幻读。4.Serializable避免所有并发问题,但降低并发性。选择合适的隔离级别需平衡数据一致性和性能需求。

MySQL与其他数据库:比较选项MySQL与其他数据库:比较选项Apr 15, 2025 am 12:08 AM

MySQL适合Web应用和内容管理系统,因其开源、高性能和易用性而受欢迎。1)与PostgreSQL相比,MySQL在简单查询和高并发读操作上表现更好。2)相较Oracle,MySQL因开源和低成本更受中小企业青睐。3)对比MicrosoftSQLServer,MySQL更适合跨平台应用。4)与MongoDB不同,MySQL更适用于结构化数据和事务处理。

MySQL索引基数如何影响查询性能?MySQL索引基数如何影响查询性能?Apr 14, 2025 am 12:18 AM

MySQL索引基数对查询性能有显着影响:1.高基数索引能更有效地缩小数据范围,提高查询效率;2.低基数索引可能导致全表扫描,降低查询性能;3.在联合索引中,应将高基数列放在前面以优化查询。

MySQL:新用户的资源和教程MySQL:新用户的资源和教程Apr 14, 2025 am 12:16 AM

MySQL学习路径包括基础知识、核心概念、使用示例和优化技巧。1)了解表、行、列、SQL查询等基础概念。2)学习MySQL的定义、工作原理和优势。3)掌握基本CRUD操作和高级用法,如索引和存储过程。4)熟悉常见错误调试和性能优化建议,如合理使用索引和优化查询。通过这些步骤,你将全面掌握MySQL的使用和优化。

现实世界Mysql:示例和用例现实世界Mysql:示例和用例Apr 14, 2025 am 12:15 AM

MySQL在现实世界的应用包括基础数据库设计和复杂查询优化。1)基本用法:用于存储和管理用户数据,如插入、查询、更新和删除用户信息。2)高级用法:处理复杂业务逻辑,如电子商务平台的订单和库存管理。3)性能优化:通过合理使用索引、分区表和查询缓存来提升性能。

See all articles

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

AI Hentai Generator

AI Hentai Generator

免费生成ai无尽的。

热门文章

R.E.P.O.能量晶体解释及其做什么(黄色晶体)
4 周前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳图形设置
4 周前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.如果您听不到任何人,如何修复音频
4 周前By尊渡假赌尊渡假赌尊渡假赌
WWE 2K25:如何解锁Myrise中的所有内容
1 个月前By尊渡假赌尊渡假赌尊渡假赌

热工具

安全考试浏览器

安全考试浏览器

Safe Exam Browser是一个安全的浏览器环境,用于安全地进行在线考试。该软件将任何计算机变成一个安全的工作站。它控制对任何实用工具的访问,并防止学生使用未经授权的资源。

EditPlus 中文破解版

EditPlus 中文破解版

体积小,语法高亮,不支持代码提示功能

DVWA

DVWA

Damn Vulnerable Web App (DVWA) 是一个PHP/MySQL的Web应用程序,非常容易受到攻击。它的主要目标是成为安全专业人员在合法环境中测试自己的技能和工具的辅助工具,帮助Web开发人员更好地理解保护Web应用程序的过程,并帮助教师/学生在课堂环境中教授/学习Web应用程序安全。DVWA的目标是通过简单直接的界面练习一些最常见的Web漏洞,难度各不相同。请注意,该软件中

Dreamweaver CS6

Dreamweaver CS6

视觉化网页开发工具

适用于 Eclipse 的 SAP NetWeaver 服务器适配器

适用于 Eclipse 的 SAP NetWeaver 服务器适配器

将Eclipse与SAP NetWeaver应用服务器集成。