14 优化实例

作者: 笑Skr人啊 | 来源:发表于2017-04-27 11:42 被阅读0次

本篇例子显示出一个多表JOIN如何能使用EXPLAIN提供的信息逐步被优化。

假定你有下面所示的SELECT语句,计划使用EXPLAIN来检查它:

EXPLAIN 
    SELECT
        tt.TicketNumber,
        tt.TimeIn,
        tt.ProjectReference,
        tt.EstimatedShipDate,
        tt.ActualShipDate,
        tt.ClientID,
        tt.ServiceCodes,
        tt.RepetitiveID,
        tt.CurrentProcess,
        tt.CurrentDPPerson,
        tt.RecordVolume,
        tt.DPPrinted,
        et.COUNTRY,
        et_1.COUNTRY,
        do.CUSTNAME
    FROM
        tt,
        et,
        et AS et_1,
        do
    WHERE
        tt.SubmitTime IS NULL
    AND tt.ActualPC = et.EMPLOYID
    AND tt.AssignedPC = et_1.EMPLOYID
    AND tt.ClientID = do.CUSTNMBR;


  • 对于这个例子,假定被比较的列声明如下:
列类型
tt ActualPC CHAR(10)
tt AssignedPC CHAR(10)
tt ClientID CHAR(10)
et EMPLOYID CHAR(15)
do CUSTNMBR CHAR(15)
  • 表有下面的索引:
索引
tt ActualPC
tt AssignedPC
tt ClientID
et EMPLOYID(主键)
do CUSTNMBR(主键)

-tt.ActualPC值不是均匀分布的。

table type possible_keys key key_len ref rows
et ALL PRIMARY NULL NULL NULL 74
do ALL PRIMARY NULL NULL NULL 2135
et_1 ALL PRIMARY NULL NULL NULL 74
tt ALL AssignedPC,ClientID, ActualPC NULL NULL NULL 3872

因为type对每张表是ALL,这个输出显示MySQL正在对所有表产生一个笛卡尔乘积;即每一个行的组合!这将花相当长的时间,因为必须检查每张表的行数的乘积!对于一个实例,这是74 * 2135 * 74 * 3872 = 45,268,558,720行。如果表更大,你只能想象它将花多长时间……

这里的一个问题是MySQL能更高效地在声明具有相同类型和尺寸的列上使用索引。在本文中,VARCHAR和CHAR是相同的,除非它们声明为不同的长度。因为tt.ActualPC被声明为CHAR(10)并且et.EMPLOYID被声明为CHAR(15),长度不匹配。

为了修正在列长度上的不同,使用ALTER TABLE将ActualPC的长度从10个字符变为15个字符:

mysql> ALTER TABLE tt MODIFY ActualPC VARCHAR(15);

现在tt.ActualPC和et.EMPLOYID都是VARCHAR(15),再执行EXPLAIN语句产生这个结果:

table type possible_keys key key_len ref rows Extra
tt ALL AssignedPC,ClientID, ActualPC NULL NULL NULL 3872 Using where
do ALL PRIMARY NULL NULL NULL 2135 range checked for each record (key map: 1)
et_1 ALL PRIMARY NULL NULL NULL 74 range checked for each record (key map: 1)
et eq_ref PRIMARY PRIMARY 15 tt.ActualPC 1 --

这不是完美的,但是好一些了:rows值的乘积少了一个因子74。这个版本在几秒内执行完。

第2种方法能消除tt.AssignedPC = et_1.EMPLOYID和tt.ClientID = do.CUSTNMBR比较的列的长度失配问题:

mysql> ALTER TABLE tt MODIFY AssignedPC VARCHAR(15),MODIFY ClientID   VARCHAR(15);

EXPLAIN产生的输出显示在下面:

table type possible_keys key key_len ref rows Extra
et ALL PRIMARY NULL NULL NULL 74
tt ref AssignedPC,ClientID, ActualPC ActualPC 15 et.EMPLOYID 52 Using where
et_1 eq_ref PRIMARY PRIMARY 15 tt.AssignedPC 1
do eq_ref PRIMARY PRIMARY 15 tt.ClientID 1

剩下的问题是,默认情况,MySQL假设在tt.ActualPC列的值是均匀分布的,并且对tt表不是这样。幸好,很容易告诉MySQL来分析关键字分布:

mysql> ANALYZE TABLE tt;

现在联接是“完美”的了,而且EXPLAIN产生这个结果:

table type possible_keys key key_len ref rows Extra
tt ALL AssignedPC ,ClientID, ActualPC NULL NULL NULL 3872 Using where
et eq_ref PRIMARY PRIMARY 15 tt.ActualPC 1
et_1 eq_ref PRIMARY PRIMARY 15 tt.AssignedPC 1
do eq_ref PRIMARY PRIMARY 15 tt.ClientID 1

注意在从EXPLAIN输出的rows列是一个来自MySQL联接优化器的“教育猜测”。你应该检查数字是否接近事实。如果不是,可以通过在SELECT语句里面使用STRAIGHT_JOIN并且试着在FROM子句以不同的次序列出表,可能得到更好的性能。

相关文章

  • 14 优化实例

    本篇例子显示出一个多表JOIN如何能使用EXPLAIN提供的信息逐步被优化。 假定你有下面所示的SELECT语句,...

  • Java 实例 - 字符串优化

    Java 实例 - 字符串优化 Java 实例以下实例演示了通过 String.intern() 方法来优化字符串...

  • gluon.Trainer()

    #定义优化算法 #Trainer实例,学习率=0.03小批量随机梯度下降(sgd)为优化算法 #迭代net实例 #...

  • js数组重组,数字类型到对象类型

    原数组 改变后数组 代码实例 优化操作

  • 4.MySQL性能优化

    参数优化--innodb_buffer_pool_size 单实例性能实例需求实例标准化 注:源码中在innodb...

  • Go语言:冒泡排序 及其 三种优化方法

    代码实例(未优化): 代码实例(优化一): 在全部数据中,前面数比后面数大,就会发生交换,把大的数换到后面去 因此...

  • mysql优化实例

    优化原则 过滤条件 尽可能前置 连接时 索引先行 临时表除非万不得已,慎用 除非性能问题显现, 否则没有优化的必要...

  • 数据库优化 - 实例优化

    从网上去搜数据库优化基本都是从SQL层次进行优化的,很少有提及到数据库本身的实例优化。就算有也都是基于某个特定数据...

  • 数据库优化 - 实例优化

    从网上去搜数据库优化基本都是从SQL层次进行优化的,很少有提及到数据库本身的实例优化。就算有也都是基于某个特定数据...

  • (四)从零编写PHP容器-添加绑定解析

    项目源码 功能实现 代码优化 添加绑定解析,优先从绑定实例中获取参数实例 代码实现 Container 注: Ab...

网友评论

    本文标题:14 优化实例

    本文链接:https://www.haomeiwen.com/subject/mqpgzttx.html