[前][次][番号順一覧][スレッド一覧]

mysql:15727

From: "ochiai" <"ochiai" <s.ochiai@xxxxxxxxxx>>
Date: Wed, 11 Apr 2012 17:03:02 +0900
Subject: [mysql 15727] Re: Left Join句を付けたUPDATE処理時間が非常に長くかかって(長文)

中川様
平塚様

お忙しい所、ご指導いただきながら、返信が遅れましたこと、申し訳ありません。
自分で色々試して、整理するのに手間取りました。

以下のように実行しましたが、うまくいきませんでした。

なお、そもそもやりたいことは、明細のレコードからなるテーブル(明細テーブル)から、明細をあるキーでまとめたテーブル(主テーブル)を作成し、主テーブルのIDを明細テーブルに設定することです。

1.ケース1(実際のテーブルで行った結果)・・・期待する結果にならなかった
2.テスト環境でに実行結果・・・・・・・・・・・・・・・期待する結果にはなったが、上記の目的に合わない。

長文ですが、よろしくお願いします。

1.ケース1(実際のテーブルで行った結果)

show create table の結果
なお、テーブル名はフィールド名は書き直しています。

mysql> show create table `table-a`;
+-------------++
| Table       | Create Table|
+-------------++
| table-a | CREATE TABLE `table-a` (
  `id` int(11) NOT NULL,
  `table-bID` int(11) DEFAULT NULL COMMENT '主テーブルのID。後付けで設定する。',
  `F1` varchar(30) DEFAULT NULL COMMENT 'グループ化キー',
  `Flag` tinyint(1) DEFAULT NULL COMMENT '',
  ..........(35個のフィールド)
  PRIMARY KEY (`id`),
  KEY `table-bID` (`table-bID`),
  KEY `F1` (`F1`),
  KEY `F2` (`F2`),  ...フィールド定義分省略
  KEY `F3` (`F3`),
  KEY `F4` (`F4`),
  KEY `F5` (`F5`),
  KEY `F6` (`F6`),
  KEY `F7` (`F7`),
  KEY `F8` (`F8`),
  KEY `F9` (`F9`),
  KEY `F10` (`F10`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='明細テーブル:table-aID' |
+-------------++
1 row in set (0.02 sec)

mysql> show create table `table-b`;
+------------+
| Table      | Create Table |
+------------+
| table-b | CREATE TABLE `table-b` (
  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '',
  `table-aID` int(11) DEFAULT NULL COMMENT '',
  `meisai` int(11) DEFAULT '0' COMMENT '',
  `F1` varchar(30) DEFAULT NULL COMMENT 'グループ化キー',
  `Flag` tinyint(1) DEFAULT '0' COMMENT '',
  ..........(35個のフィールド)
  PRIMARY KEY (`id`),
  UNIQUE KEY `F1_UNIQUE` (`F1`),
  KEY `F2` (`F2`),
  KEY `F3` (`F3`),
  KEY `F4` (`F4`),
  KEY `F5` (`F5`),
  KEY `F6` (`F6`),
  KEY `F7` (`F7`),
  KEY `F8` (`F8`),
  KEY `F9` (`F9`),
  KEY `F10` (`F10`),
  KEY `F11` (`F11`)
) ENGINE=InnoDB AUTO_INCREMENT=393211 DEFAULT CHARSET=cp932 COMMENT='主テーブル。' |
+------------+
1 row in set (0.00 sec)

mysql> explain select 
`table-a`.`ID`,`table-a`.`muneID`,`table-b`.`id`,`table-a`.`F1`,`table-b`.`F1`
    -> from `table-a` left join `table-b` on
    ->     (`table-a`.`F1`=`table-b`.`F1`);
+----+-------------+-------------+-------+---------------+--------------------+---------+------+--------+-------------+
| id | select_type | table       | type  | possible_keys | key 
| key_len | ref  | rows   | Extra       |
+----+-------------+-------------+-------+---------------+--------------------+---------+------+--------+-------------+
|  1 | SIMPLE      | table-a | ALL   | NULL          | NULL               | 
NULL    | NULL | 183578 |             |
|  1 | SIMPLE      | table-b  | index | NULL          | F1_UNIQUE | 63 
| NULL | 138317 | Using index |
+----+-------------+-------------+-------+---------------+--------------------+---------+------+--------+-------------+
2 rows in set (0.00 sec)

table-bのtypeはindexのままで、possible_keys がNULL、ref もNULLで、rowsは1ではなく138317と状況は変わりませんでした。
主テーブルのインデックスがどのようになっているか見てみました。
これを見ると、F1_UNIQUE はNon_unique が0となっているので、ユニークキーでしょう。 


mysql> show index from `table-b`;
+------------+------------+--------------------+--------------+---------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table      | Non_unique | Key_name           | Seq_in_index | Column_name 
| Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment 
| Index_comment |
+------------+------------+--------------------+--------------+---------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| table-b |          0 | PRIMARY            |            1 | id            | 
A         |      137304 |     NULL | NULL   |      | BTREE      |         | 
|
| table-b |          0 | F1_UNIQUE |            1 | F1   | A         | 
137304 |     NULL | NULL   | YES  | BTREE      |         |               |
| table-b |          1 | F2           |            1 | F2      | A         | 
137304 |     NULL | NULL   |      | BTREE      |         |               |
| table-b |          1 | F3           |            1 | F3      | A         | 
137304 |     NULL | NULL   |      | BTREE      |         |               |
| table-b |          1 | F4            |            1 | F4       | A 
|       68652 |     NULL | NULL   | YES  | BTREE      |         | 
|
| table-b |          1 | F5        |            1 | F5   | A         | 
312 |     NULL | NULL   | YES  | BTREE      |         |               |
| table-b |          1 | F6        |            1 | F6   | A         | 
65 |     NULL | NULL   | YES  | BTREE      |         |               |
| table-b |          1 | F7      |            1 | F7 | A         | 
137304 |     NULL | NULL   | YES  | BTREE      |         |               |
| table-b |          1 | F8         |            1 | F8    | A         | 
435 |     NULL | NULL   | YES  | BTREE      |         |               |
| table-b |          1 | F9         |            1 | F9    | A         | 
3 |     NULL | NULL   | YES  | BTREE      |         |               |
| table-b |          1 | F10       |            1 | F10  | A         | 
68652 |     NULL | NULL   | YES  | BTREE      |         |               |
| table-b |          1 | F11           |            1 | F11      | A 
|      137304 |     NULL | NULL   | YES  | BTREE      |         | 
|
+------------+------------+--------------------+--------------+---------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
12 rows in set (0.58 sec)


今気づいたことですが、手違いでtable-aとtable-bのキャラクタセットが異なっていました。本来はcp932で統一します。
これは影響するでしょうか?

2.テスト環境でに実行結果

フィールドサイズやインデックス数が多いのが原因かなと考え、元のスキーマから対象となるテーブルの一部のフィールドのみを抽出したテーブルをtestというスキーマにInsert INTOコマンドで新たに作成し、試してみ 
ました。

1)テーブル作成で実行したSQLは下記の通りです。

USE `test`;

drop tables if exists `table-a`;

CREATE TABLE `table-a` (
  `id` int(11) NOT NULL,
  `table-b_ID` int(11) DEFAULT NULL COMMENT '後付けで設定',
  `F1` varchar(30) DEFAULT NULL COMMENT 'グループ化キー',
  PRIMARY KEY (`id`),
  KEY `table-b_ID` (`table-b_ID`),
  KEY `F1` (`F1`)
) ENGINE=InnoDB DEFAULT CHARSET=cp932 COMMENT='明細テーブル';


drop tables if exists `table-b`;

CREATE TABLE `table-b` (
  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '',
  `table-a_ID` int(11) DEFAULT NULL COMMENT '',
  `meisai` int(11) DEFAULT '0' COMMENT '',
  `F1` varchar(30) NOT NULL COMMENT 'グループ化キー。ユニーク',
  PRIMARY KEY (`id`),
  UNIQUE KEY `F1_UNIQUE` (`F1`)
) ENGINE=InnoDB DEFAULT CHARSET=cp932 COMMENT='明細テーブルをグループ化したテーブル';

#`table-a`を元のスキーマ`aaa`から一部コピー
INSERT INTO `table-a` (
 `id`,
 `F1`)
    SELECT
 `T1`.`id`,
 `T1`.`F1`
    FROM `aaa`.`T1`;

#`table-a`を`F1`でグループ化して`table-b`を作成
INSERT INTO `table-b` (
 `table-a_ID`,
 `meisai`,
 `F1`)
    SELECT
 `table-a`.`id`,
 COUNT(`table-a`.`F1`),
 `table-a`.`F1`
    FROM `table-a`
 GROUP BY `table-a`.`F1`;

2)show create tableの結果

mysql> show create table `table-a`;
+---------+
| Table   | Create Table|
+---------+
| table-a | CREATE TABLE `table-a` (
  `id` int(11) NOT NULL,
  `table-b_ID` int(11) DEFAULT NULL COMMENT '後付けで設定',
  `F1` varchar(30) DEFAULT NULL COMMENT 'グループ化キー',
  PRIMARY KEY (`id`),
  KEY `table-b_ID` (`table-b_ID`),
  KEY `F1` (`F1`)
) ENGINE=InnoDB DEFAULT CHARSET=cp932 COMMENT='明細テーブル' 
|
+---------+
1 row in set (0.00 sec)

mysql> show create table `table-b`;
+---------+
| Table   | Create Table|
+---------+
| table-b | CREATE TABLE `table-b` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `table-a_ID` int(11) DEFAULT NULL,
  `meisai` int(11) DEFAULT '0',
  `F1` varchar(30) NOT NULL COMMENT 'グループ化キー。ユニーク',
  PRIMARY KEY (`id`),
  UNIQUE KEY `F1_UNIQUE` (`F1`)
) ENGINE=InnoDB AUTO_INCREMENT=196606 DEFAULT CHARSET=cp932 COMMENT='明細テーブルをグループ化したテーブル'                               |
+---------+
1 row in set (0.00 sec)

3)explainの結果1

mysql> explain select
    ->      `table-a`.`id`,
    ->      `table-a`.`table-b_ID`,
    ->      `table-b`.`id`,
    ->      `table-a`.`F1`,
    ->      `table-b`.`F1`,
    ->      `table-b`.`meisai`
    ->      from `table-a`
    ->    left join `table-b` ON `table-b`.`F1`=`table-a`.`F1`;
+----+-------------+---------+--------+---------------+-----------+---------+-----------------+--------+-------+
| id | select_type | table   | type   | possible_keys | key       | key_len 
| ref             | rows   | Extra |
+----+-------------+---------+--------+---------------+-----------+---------+-----------------+--------+-------+
|  1 | SIMPLE      | table-a | ALL    | NULL          | NULL      | NULL 
| NULL            | 220419 |       |
|  1 | SIMPLE      | table-b | eq_ref | F1_UNIQUE     | F1_UNIQUE | 62 
| test.table-a.F1 |      1 |       |
+----+-------------+---------+--------+---------------+-----------+---------+-----------------+--------+-------+
2 rows in set (0.00 sec)

ここでは、望む結果が出ています。

4)USE INDEXを使ったexplainの結果2

mysql> explain select
    ->      `table-a`.`id`,
    ->      `table-a`.`table-b_ID`,
    ->      `table-b`.`id`,
    ->      `table-a`.`F1`,
    ->      `table-b`.`F1`,
    ->      `table-b`.`meisai`
    ->      from `table-a`
    ->    left join `table-b` USE INDEX (`F1_UNIQUE`) ON 
`table-b`.`F1`=`table-a`.`F1`;
+----+-------------+---------+--------+---------------+-----------+---------+-----------------+--------+-------+
| id | select_type | table   | type   | possible_keys | key       | key_len 
| ref             | rows   | Extra |
+----+-------------+---------+--------+---------------+-----------+---------+-----------------+--------+-------+
|  1 | SIMPLE      | table-a | ALL    | NULL          | NULL      | NULL 
| NULL            | 220419 |       |
|  1 | SIMPLE      | table-b | eq_ref | F1_UNIQUE     | F1_UNIQUE | 62 
| test.table-a.F1 |      1 |       |
+----+-------------+---------+--------+---------------+-----------+---------+-----------------+--------+-------+
2 rows in set (0.00 sec)

USE INDEXを使っても使わなくても結果は同じでした。

なぜ、元のテーブルではうまくいかないのでしょうか?


----- Original Message ----- 
From: "中川貴" <nora1962@xxxxxxxxxx>
To: <ml@xxxxxxxxxx>
Sent: Friday, March 30, 2012 1:27 AM
Subject: [mysql 15713] Re: Left Join句を付けたUPDATE処理時間が非常に長くかかって 



> (2012/03/29 17:58), ochiai wrote:
>> 中川様
>> ありがとうございます。
>>
>> 実行結果は以下の通りとなりました。
>>
>> select_type table type possible_keys key key_len ref rows Extra
>> SIMPLE table-a ALL NULL NULL NULL NULL 20万
>> SIMPLE table-b index NULL Kb 63 NULL 14万 Usingindex
>>
>> ----- Original Message ----- From: "中川 貴" <takashi.nakagawa@xxxxxxxxxx>
>> To: <ml@xxxxxxxxxx>
>> Sent: Thursday, March 29, 2012 5:46 PM
>> Subject: [mysql 15709] Re: Left Join句を付けたUPDATE処理時間が非常に長くかかって
> 中川です。
> 帰宅しました。
> 自宅から返信します。
> すでにレスされている方がいらっしゃいますが、現在の実行計画ではJOINにINDEXが使用されていません。
> (USE INDEX 指定してもテーブルアクセスの際にINDEX経由であるだけで却って非効率)
>
> table-bの行のrefがNULLになっているのが証拠です(本来ならtable-a.Kaになるべき)。 
> 
> 考えられるのは索引の作成方法が誤っているか、`table-a`.`Ka`と`table-b`.`kb`の属性が違うことでしょうか。
> 平塚さんのおっしゃるとおりに「table-a」と「table-b」の「show create 
>  table」の結果を教えて下さい。
> それではよろしくお願いします。
>
>
> 


[前][次][番号順一覧][スレッド一覧]

     15703 2012-03-29 15:08 ["ochiai" <s.ochiai@x] Left Join句を付けたUPDATE処理時間が非常に長くかかって
     15705 2012-03-29 16:56 ┣[中川 貴 <takashi.nak]                                       
     15706 2012-03-29 17:01 ┗[中川 貴 <takashi.nak]                                       
     15707 2012-03-29 17:12  ┗[中川 貴 <takashi.nak]                                     
     15708 2012-03-29 17:42   ┗["ochiai" <s.ochiai@x]                                   
     15709 2012-03-29 17:46    ┣[中川 貴 <takashi.nak]                                 
     15711 2012-03-29 17:58    ┃┗["ochiai" <s.ochiai@x]                               
     15712 2012-03-29 20:25    ┃ ┣[HIRATSUKA Sadao <hir]                             
     15713 2012-03-30 01:27    ┃ ┗[中川貴 <nora1962@xxx]                             
->   15727 2012-04-11 17:03    ┃  ┗["ochiai" <s.ochiai@x] Re: Left Join句を付けたUPDATE処理時間が非常に長くかかって(長文)
     15728 2012-04-11 18:24    ┃   ┗[中川 貴 <takashi.nak]                         
     15729 2012-04-12 09:46    ┃    ┗[HIRATSUKA Sadao <hir]                       
     15730 2012-04-13 10:32    ┃     ┗["ochiai" <s.ochiai@x] Re: Left Join句を付けたUPDATE処理時間が非常に長くかかって(解決御礼)
     15733 2012-04-13 11:13    ┃      ┗[HIRATSUKA Sadao <hir]                   
     15710 2012-03-29 17:47    ┗[Masaaki Matsuyama <m]