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]