2017-08-03 15 views
0

私はこれらの2つの違い(行2)を理解していませんEXPLAIN。たぶん、誰かが私のヒントを持っているのかもしれません。質問速度の急激な差異

スロークエリは、(そのクエリですべての行を照会等しい)12秒で終了し、結合テーブルがちょうど3レコードがありながら、整数の列に参加を使用しています:高速のクエリはわずか数を消費

SELECT `inv_assets`.`id` AS `id`, `site`.`description` AS `sitename`, 
    (SELECT COALESCE(DATE_FORMAT(CONVERT_TZ(MIN(inspdate),'UTC','Europe/Vienna'),'%Y-%m-%d'),'') 
    FROM `mobuto_inv_inspections` AS `nextinsp` 
    WHERE ((`nextinsp`.`objectlink` = `inv_assets`.`id` 
      AND `nextinsp`.`inspdate` >= NOW())) 
    ) AS `nextinsp` 
FROM `mobuto_inv_assets` AS `inv_assets` 
LEFT JOIN `mobuto_inv_sites` AS `site` 
    ON (`site`.`siteid` = `inv_assets`.`site` 
    AND `site`.`_state` IN (2,0)) 
ORDER BY `inv_assets`.`type` ASC LIMIT 0, 20; 

+----+--------------------+------------+--------+----------------+---------+---------+------------------------------+-------+----------------------------------------------------+ 
| id | select_type  | table  | type | possible_keys | key  | key_len | ref       | rows | Extra            | 
+----+--------------------+------------+--------+----------------+---------+---------+------------------------------+-------+----------------------------------------------------+ 
| 1 | PRIMARY   | inv_assets | ALL | NULL   | NULL | NULL | NULL       | 24857 | Using temporary; Using filesort     | 
| 1 | PRIMARY   | site  | ALL | PRIMARY,_state | NULL | NULL | NULL       |  3 | Using where; Using join buffer (Block Nested Loop) | 
| 2 | DEPENDENT SUBQUERY | nextinsp | ALL | inspdate  | NULL | NULL | NULL       | 915 | Using where          | 
+----+--------------------+------------+--------+----------------+---------+---------+------------------------------+-------+----------------------------------------------------+ 

を第二の画分、VARCHARに参加(32)の列と結合テーブルを使用すると、1352本の記録を持っている:

SELECT `inv_assets`.`id` AS `id`, `guarantor`.`lastname` AS `guarantoruname`, 
     (SELECT COALESCE(DATE_FORMAT(CONVERT_TZ(MIN(inspdate),'UTC','Europe/Vienna'),'%Y-%m-%d'),'') 
     FROM `mobuto_inv_inspections` AS `nextinsp` 
     LEFT JOIN `users` AS `saveuser` 
     ON (`saveuser`.`uid` = `nextinsp`.`saveuser` 
      AND `saveuser`.`_state` = '0') 
     WHERE ((`nextinsp`.`objectlink` = `inv_assets`.`id` 
       AND `nextinsp`.`inspdate` >= NOW())) 
     ) AS `nextinsp` 
FROM `mobuto_inv_assets` AS `inv_assets` 
LEFT JOIN `users` AS `guarantor` 
ON (`guarantor`.`uid` = `inv_assets`.`guarantor` 
    AND `guarantor`.`_state` = '0') 
ORDER BY `inv_assets`.`type` ASC LIMIT 0, 20; 

+----+--------------------+------------+--------+----------------+---------+---------+---------------------------------+-------+----------------+ 
| id | select_type  | table  | type | possible_keys | key  | key_len | ref        | rows | Extra   | 
+----+--------------------+------------+--------+----------------+---------+---------+---------------------------------+-------+----------------+ 
| 1 | PRIMARY   | inv_assets | ALL | NULL   | NULL | NULL | NULL       | 24857 | Using filesort | 
| 1 | PRIMARY   | guarantor | eq_ref | PRIMARY,_state | PRIMARY | 98  | mobuto_dev.inv_assets.guarantor |  1 | Using where | 
| 2 | DEPENDENT SUBQUERY | nextinsp | ALL | inspdate  | NULL | NULL | NULL       | 915 | Using where | 
| 2 | DEPENDENT SUBQUERY | saveuser | eq_ref | PRIMARY,_state | PRIMARY | 98  | mobuto_dev.nextinsp.saveuser |  1 | Using where | 
+----+--------------------+------------+--------+----------------+---------+---------+---------------------------------+-------+----------------+ 

私が参加し、テーブルの列(description)を削除すると私には奇妙なことは、あります'column-select-part'(結合ステイ私はIMHO mysqlは使用しないときにはそれを最適化しません)、速度は戻っています(mysqlは一時テーブルを使用せず、説明は速いものと同じように見えるので、type=eq_ref)。

しかし、最初のサンプルでは、​​選択されていない列が選択されている場合にのみ、なぜこれが機能しますか? @Wilsonハウクによって要求されるように

CREATE TABLE `mobuto_inv_assets` (
    `id` int(11) NOT NULL AUTO_INCREMENT, 
    `invnum` varchar(10) NOT NULL, 
    `oebglcat` varchar(4) NOT NULL, 
    `mark` varchar(100) NOT NULL, 
    `type` varchar(100) NOT NULL, 
    `serialnum` varchar(100) NOT NULL, 
    `desc` varchar(100) NOT NULL, 
    `site` int(11) NOT NULL DEFAULT '0', 
    `licnum` varchar(20) NOT NULL DEFAULT '', 
    `inquirer` varchar(100) NOT NULL DEFAULT '', 
    `inqdate` date NOT NULL DEFAULT '0000-00-00', 
    `supplier` varchar(100) NOT NULL DEFAULT '', 
    `suppldate` date NOT NULL DEFAULT '0000-00-00', 
    `supplnumber` varchar(30) NOT NULL DEFAULT '', 
    `invoicedate` date NOT NULL DEFAULT '0000-00-00', 
    `invoicenumber` varchar(30) NOT NULL DEFAULT '', 
    `purchaseprice` decimal(11,2) NOT NULL DEFAULT '0.00', 
    `leased` varchar(1) NOT NULL DEFAULT 'N', 
    `leasingcompany` varchar(100) NOT NULL DEFAULT '', 
    `leasingnumber` varchar(30) NOT NULL DEFAULT '', 
    `notes` text NOT NULL, 
    `inspnotes` text NOT NULL, 
    `inactive` varchar(1) NOT NULL DEFAULT 'N', 
    `maintain` varchar(1) NOT NULL DEFAULT 'Y', 
    `asset` varchar(1) NOT NULL DEFAULT 'Y', 
    `inspection` varchar(1) NOT NULL DEFAULT '', 
    `inspperson` varchar(100) NOT NULL DEFAULT '', 
    `guarantor` varchar(32) NOT NULL DEFAULT '', 
    `saveuser` varchar(32) NOT NULL, 
    `savetime` int(11) NOT NULL, 
    `recordid` varchar(32) NOT NULL, 
    `_state` int(11) NOT NULL DEFAULT '0', 
    PRIMARY KEY (`id`), 
    UNIQUE KEY `invnum` (`invnum`), 
    KEY `_state` (`_state`), 
    KEY `site` (`site`) 
) ENGINE=InnoDB AUTO_INCREMENT=30707 DEFAULT CHARSET=utf8; 


CREATE TABLE `mobuto_inv_sites` (
    `siteid` int(11) NOT NULL AUTO_INCREMENT, 
    `description` varchar(100) NOT NULL, 
    `saveuser` varchar(32) NOT NULL, 
    `savetime` int(11) NOT NULL, 
    `recordid` varchar(32) NOT NULL, 
    `_state` int(11) NOT NULL DEFAULT '0', 
    PRIMARY KEY (`siteid`), 
    KEY `_state` (`_state`) 
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8; 


mysql> SHOW INDEX FROM mobuto_inv_assets; 
+-------------------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+ 
| Table    | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment | 
+-------------------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+ 
| mobuto_inv_assets |   0 | PRIMARY |   1 | id   | A   |  24857 |  NULL | NULL |  | BTREE  |   |    | 
| mobuto_inv_assets |   0 | invnum |   1 | invnum  | A   |  24857 |  NULL | NULL |  | BTREE  |   |    | 
| mobuto_inv_assets |   1 | _state |   1 | _state  | A   |   4 |  NULL | NULL |  | BTREE  |   |    | 
+-------------------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+ 

変更:

  • mobuto_inv_assetsの列siteに追加指数(ほぼ半分秒で実行速度を減少)
  • が列nextinspは、最初のクエリで行方不明になったようです。クエリの書式設定中に失われた可能性があります。もちろん、(最後の行は削除)それはそこ使用(他の2秒を保存)し、そのEXPLAINが更新されないようsaveuserが参加削除速い1
  • と同じであるはず
  • SHOW INDEX FROM mobuto_inv_sites

    +------------------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+ 
    | Table   | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment | 
    +------------------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+ 
    | mobuto_inv_sites |   0 | PRIMARY |   1 | siteid  | A   |   3 |  NULL | NULL |  | BTREE  |   |    | 
    | mobuto_inv_sites |   1 | _state |   1 | _state  | A   |   3 |  NULL | NULL |  | BTREE  |   |    | 
    +------------------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+ 
    
    を追加しました
+1

主にinv_assetsテーブルのSHOW CREATE TABLEステートメントを表示できますか? – Strawberry

+0

EXPLAINの 'key'カラムを見てください –

答えて

0

最初のクエリでは、2番目のクエリよりもキーの使用量が少なくなります。説明計画のpossible_keys列には、キーを使用できる場所が示されていますが、key列には実際に使用されている場所が示されています。

あなたのDBの構造を見て、JOINとWHERE節でこれらのキーをさらに活用してスピードアップすることをお勧めします。

私は、あなたが選択列を変更しており、速度が変化していると言うときに、クエリがキャッシュされていないことを確認したいと思います。

+0

はい、クエリはキャッシュされません。追加情報が質問に追加されました。追加/変更されたインデックスは、必要なときに配置することができます。 – toshniba

0

最初のクエリは、単純に24857 * 3 * 915 * 1 = 68,232,465個の行を考慮したROWS列のヒントによって発生する可能性があります。 2番目の問合せでは1秒未満ROWS列のヒントは、単純に24857 * 1 * 915 * 1 = 22,744,155の合計行を考慮したものです。最初のクエリでBlock Nested Loop処理を使用することは、応答を遅延させる大きな要因となります。
SHOW CREATE TABLEのmobuto_inv_assetsとmobuto_inv_sitesの結果を投稿してください。 mobuto_inv_assetsとmobuto_inv_sitesからのSHOW INDEXの結果も投稿してください。この追加情報を使用すると、RBAR(Row By Agonizing Row処理)で非常に時間がかかるCPUのネストループ処理を回避するSELECT ....クエリの改善を提案することができます。追加の索引付けが必要な場合があります。

+0

これまでの分析に感謝します。要求された情報を質問に追加しました。 – toshniba

0

2つのSHOW CREATE TABLEをお送りいただきありがとうございます。 のインデックスを追加することを検討してください。システムにスペースがある場合は、ALTER TABLE mobuto_inv_sites ADD INDEXサイト - を追加してください。 また、query1を示すEXPLAINがクエリと一致しません。 EXPLAINで確認できるnextinspまたはsaveusedはクエリで参照されません。 再度テストし、必要な実行時間の短縮を示す機会がある場合は、索引を作成した後でquery1のEXPLAINを置き換えてください。 の結果をmobuto_inv_sitesから表示することができれば、あなたのデータとカーディナリティの範囲を見ることができます。

+0

ありがとうございました!質問が要求通りに更新されました。どうぞよろしくお願いします。 – toshniba

0

inv_assets行は次のようにQuery1をを変更することを検討 ACCURATE _stateデータが移入されている場合:
inv_assetsを選択します。 id AS id,sitedescriptionsitename、 AS(SELECT COALESCE(DATE_FORMAT(CONVERT_TZ(MIN(inspdate)、 'UTC'、 'ヨーロッパ/ウィーン') '%Y-%m-%d' では)、 '')nextinsp AS mobuto_inv_inspections FROM WHERE((nextinspobjectlink = inv_assetsidnextinsp。> = NOW())inspdate) ) nextinsp AS mobuto_inv_assets FROM inv_assets AS inv_assets_state = 2 OR inv_assets_state = 0
LEFTはinv_assets BY mobuto_inv_sites ON site AS( sitesitesiteid = inv_assets AND site_state IN(2,0)) 結合順序。 type ASC LIMIT 0,20;

EXPLAINは、テーブルスキャンとその後のブロックネストループ処理を避ける必要があります。

inv_assetsの_stateデータがすべての行でACCURATEでない場合、これは機能しません。

2017-08-10 update 09:42 CTは、QUERY、EXPLAIN結果、関連テーブルのSHOW CREATE TABLE tblname、関連テーブルのSHOW INDEX FROM tblnameを投稿してください。

+0

私はあなたがACCURATEの意味を本当に知っていませんが、スピードの変化なしで '_state'カラムの参照をすべて試しました。注意:_stateは(現在)0から2の値を保持できます。 – toshniba

関連する問題