您好,欢迎来到三六零分类信息网!老站,搜索引擎当天收录,欢迎发信息

MySQL数据库优化概述三_MySQL

2024/6/28 22:07:19发布25次查看
using where
where 子句将用来限制哪些记录匹配了下一个表或者发送给客户端。除非你特别地想要取得或者检查表种的所有记录,否则的话当查询的 extra 字段值不是 using where 并且表连接类型是 all 或 index 时可能表示有问题。
如果你想要让查询尽可能的快,那么就应该注意 extra 字段的值为using filesort 和 using temporary 的情况。
你可以通过 explain 的结果中 rows 字段的值的乘积大概地知道本次连接表现如何。它可以粗略地告诉我们mysql在查询过程中会查询多少条记录。如果是使用系统变量 max_join_size 来取得查询结果,这个乘积还可以用来确定会执行哪些多表 select 语句。详情请看7.5.2 tuning server parameters。
下面的例子展示了如何通过 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;
在这个例子中,先做以下假设:
要比较的字段定义如下:
table column column type
tt actualpc char(10)
tt assignedpc char(10)
tt clientid char(10)
et employid char(15)
do custnmbr char(15)
数据表的索引如下:
table index
tt actualpc
tt assignedpc
tt clientid
et employid (primary key)
do custnmbr (primary key)
tt.actualpc 的值是不均匀分布的。 在任何优化措施未采取之前,经过 explain 分析的结果显示如下:
table type possible_keys key  key_len ref  rows  extra
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,   null null    null 3872
           clientid,
           actualpc
      range checked for each record (key map: 35)
由于字段 type 的对于每个表值都是 all,这个结果意味着mysql对所有的表做一个迪卡尔积;这就是说,每条记录的组合。这将需要花很长的时间,因为需要扫描每个表总记录数乘积的总和。在这情况下,它的积是 74 * 2135 * 74 * 3872 = 45,268,558,720 条记录。如果数据表更大的话,你可以想象一下需要多长的时间。
在这里有个问题是当字段定义一样的时候,mysql就可以在这些字段上更快的是用索引(对 isam 类型的表来说,除非字段定义完全一样,否则不会使用索引)。在这个前提下,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,   null    null    null        3872    using
             clientid,                                         where
             actualpc
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,   actualpc 15      et.employid   52   using
             clientid,                                         where
             actualpc
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 的结果如下:
该用户其它信息

VIP推荐

免费发布信息,免费发布B2B信息网站平台 - 三六零分类信息网 沪ICP备09012988号-2
企业名录 Product