8

2 つのデータセット間で大幅に異なる時間で返されるクエリがあります。1 つのセット (データベース A) の場合は数秒で返され、もう 1 つのセット (データベース B) は返されます。まだ十分に待っていませんが、10 分以上かかりました。MySQL 5.1.37 を実行している問題を再現できるように、これらのデータベースを両方ともローカル マシンにダンプしました。

興味深いことに、データベース B はデータベース A よりも小さいです。

問題を再現するクエリの簡素化されたバージョンは次のとおりです。

SELECT * FROM po_shipment ps 
JOIN po_shipment_item psi USING (ship_id) 
JOIN po_alloc pa ON ps.ship_id = pa.ship_id AND pa.UID_items = psi.UID_items 
JOIN po_header ph ON pa.hdr_id = ph.hdr_id 
LEFT JOIN EVENT_TABLE ev0 ON ev0.TABLE_ID1 = ps.ship_id AND ev0.EVENT_TYPE = 'MAS0' 
LEFT JOIN EVENT_TABLE ev1 ON ev1.TABLE_ID1 = ps.ship_id AND ev1.EVENT_TYPE = 'MAS1' 
LEFT JOIN EVENT_TABLE ev2 ON ev2.TABLE_ID1 = ps.ship_id AND ev2.EVENT_TYPE = 'MAS2' 
LEFT JOIN EVENT_TABLE ev3 ON ev3.TABLE_ID1 = ps.ship_id AND ev3.EVENT_TYPE = 'MAS3' 
LEFT JOIN EVENT_TABLE ev4 ON ev4.TABLE_ID1 = ps.ship_id AND ev4.EVENT_TYPE = 'MAS4' 
LEFT JOIN EVENT_TABLE ev5 ON ev5.TABLE_ID1 = ps.ship_id AND ev5.EVENT_TYPE = 'MAS5' 
WHERE ps.eta >= '2010-03-22'
GROUP BY ps.ship_id
LIMIT 100;

~2 秒で返される最初のデータベース (A) の EXPLAIN クエリ プランは次のとおりです。

+----+-------------+-------+--------+----------------------------------------------------------------------------------------------------------------------------------------+----------------------------------+---------+------------------------------+------+----------------------------------------------+
| id | select_type | table | type   | possible_keys                                                                                                                          | key                              | key_len | ref                          | rows | Extra                                        |
+----+-------------+-------+--------+----------------------------------------------------------------------------------------------------------------------------------------+----------------------------------+---------+------------------------------+------+----------------------------------------------+
|  1 | SIMPLE      | ps    | range  | PRIMARY,IX_ETA_DATE                                                                                                                    | IX_ETA_DATE                      | 4       | NULL                         |  174 | Using where; Using temporary; Using filesort | 
|  1 | SIMPLE      | ev0   | ref    | IX_EVENT_ID_EVENT_TYPE                                                                                                                 | IX_EVENT_ID_EVENT_TYPE           | 36      | UNIVIS_PROD.ps.ship_id,const |    1 |                                              | 
|  1 | SIMPLE      | ev1   | ref    | IX_EVENT_ID_EVENT_TYPE                                                                                                                 | IX_EVENT_ID_EVENT_TYPE           | 36      | UNIVIS_PROD.ps.ship_id,const |    1 |                                              | 
|  1 | SIMPLE      | ev2   | ref    | IX_EVENT_ID_EVENT_TYPE                                                                                                                 | IX_EVENT_ID_EVENT_TYPE           | 36      | UNIVIS_PROD.ps.ship_id,const |    1 |                                              | 
|  1 | SIMPLE      | ev3   | ref    | IX_EVENT_ID_EVENT_TYPE                                                                                                                 | IX_EVENT_ID_EVENT_TYPE           | 36      | UNIVIS_PROD.ps.ship_id,const |    1 |                                              | 
|  1 | SIMPLE      | ev4   | ref    | IX_EVENT_ID_EVENT_TYPE                                                                                                                 | IX_EVENT_ID_EVENT_TYPE           | 36      | UNIVIS_PROD.ps.ship_id,const |    1 |                                              | 
|  1 | SIMPLE      | ev5   | ref    | IX_EVENT_ID_EVENT_TYPE                                                                                                                 | IX_EVENT_ID_EVENT_TYPE           | 36      | UNIVIS_PROD.ps.ship_id,const |    1 |                                              | 
|  1 | SIMPLE      | psi   | ref    | PRIMARY,IX_po_shipment_item_po_shipment1,FK_po_shipment_item_po_shipment1                                                              | IX_po_shipment_item_po_shipment1 | 4       | UNIVIS_PROD.ps.ship_id       |    1 |                                              | 
|  1 | SIMPLE      | pa    | ref    | IX_po_alloc_po_shipment_item2,IX_po_alloc_po_details_old,FK_po_alloc_po_shipment1,FK_po_alloc_po_shipment_item1,FK_po_alloc_po_header1 | FK_po_alloc_po_shipment1         | 4       | UNIVIS_PROD.psi.ship_id      |    5 | Using where                                  | 
|  1 | SIMPLE      | ph    | eq_ref | PRIMARY,IX_HDR_ID                                                                                                                      | PRIMARY                          | 4       | UNIVIS_PROD.pa.hdr_id        |    1 |                                              | 
+----+-------------+-------+--------+----------------------------------------------------------------------------------------------------------------------------------------+----------------------------------+---------+------------------------------+------+----------------------------------------------+

>600 秒で返される 2 番目のデータベース (B) の EXPLAIN クエリ プランは次のとおりです。

+----+-------------+-------+--------+----------------------------------------------------------------------------------------------------------------------------------------+----------------------------------+---------+--------------------------------+------+----------------------------------------------+
| id | select_type | table | type   | possible_keys                                                                                                                          | key                              | key_len | ref                            | rows | Extra                                        |
+----+-------------+-------+--------+----------------------------------------------------------------------------------------------------------------------------------------+----------------------------------+---------+--------------------------------+------+----------------------------------------------+
|  1 | SIMPLE      | ps    | range  | PRIMARY,IX_ETA_DATE                                                                                                                    | IX_ETA_DATE                      | 4       | NULL                           |   38 | Using where; Using temporary; Using filesort | 
|  1 | SIMPLE      | psi   | ref    | PRIMARY,IX_po_shipment_item_po_shipment1,FK_po_shipment_item_po_shipment1                                                              | IX_po_shipment_item_po_shipment1 | 4       | UNIVIS_DEV01.ps.ship_id        |    1 |                                              | 
|  1 | SIMPLE      | ev0   | ref    | IX_EVENT_ID_EVENT_TYPE                                                                                                                 | IX_EVENT_ID_EVENT_TYPE           | 36      | UNIVIS_DEV01.psi.ship_id,const |    1 |                                              | 
|  1 | SIMPLE      | ev1   | ref    | IX_EVENT_ID_EVENT_TYPE                                                                                                                 | IX_EVENT_ID_EVENT_TYPE           | 36      | UNIVIS_DEV01.psi.ship_id,const |    1 |                                              | 
|  1 | SIMPLE      | ev2   | ref    | IX_EVENT_ID_EVENT_TYPE                                                                                                                 | IX_EVENT_ID_EVENT_TYPE           | 36      | UNIVIS_DEV01.ps.ship_id,const  |    1 |                                              | 
|  1 | SIMPLE      | ev3   | ref    | IX_EVENT_ID_EVENT_TYPE                                                                                                                 | IX_EVENT_ID_EVENT_TYPE           | 36      | UNIVIS_DEV01.psi.ship_id,const |    1 |                                              | 
|  1 | SIMPLE      | ev4   | ref    | IX_EVENT_ID_EVENT_TYPE                                                                                                                 | IX_EVENT_ID_EVENT_TYPE           | 36      | UNIVIS_DEV01.psi.ship_id,const |    1 |                                              | 
|  1 | SIMPLE      | ev5   | ref    | IX_EVENT_ID_EVENT_TYPE                                                                                                                 | IX_EVENT_ID_EVENT_TYPE           | 36      | UNIVIS_DEV01.ps.ship_id,const  |    1 |                                              | 
|  1 | SIMPLE      | pa    | ref    | IX_po_alloc_po_shipment_item2,IX_po_alloc_po_details_old,FK_po_alloc_po_shipment1,FK_po_alloc_po_shipment_item1,FK_po_alloc_po_header1 | IX_po_alloc_po_shipment_item2    | 4       | UNIVIS_DEV01.ps.ship_id        |    4 | Using where                                  | 
|  1 | SIMPLE      | ph    | eq_ref | PRIMARY,IX_HDR_ID                                                                                                                      | PRIMARY                          | 4       | UNIVIS_DEV01.pa.hdr_id         |    1 |                                              | 
+----+-------------+-------+--------+----------------------------------------------------------------------------------------------------------------------------------------+----------------------------------+---------+--------------------------------+------+----------------------------------------------+

データベース B が実行されているとき、MySQL 管理者を見ることができ、状態は無期限に「tmp テーブルにコピー中」のままです。データベース A にもこの状態がありますが、ほんの 1 秒程度です。

これらのデータベース間で、テーブル構造、インデックス、キーなどに違いはありません (show create tables を実行して、それらを比較しました)。

テーブルのサイズは次のとおりです。

database A:
po_shipment 1776
po_shipment_item 1945
po_alloc 36298
po_header 71642
EVENT_TABLE 1608

database B:
po_shipment 463
po_shipment_item 470
po_alloc 3291
po_header 56149
EVENT_TABLE 1089

注意すべき点:

  • WHERE 句を削除すると、クエリは 1 秒未満で返されます。
  • GROUP BY を削除すると、クエリが 1 秒未満で返されます。
  • ev5、ev4、ev3 などを削除すると、削除するたびにクエリが高速になります。

AJ の回答後の更新: - データベース B (最大値 = 800002752) では、データベース A (最大値 = 3489) よりも ship_id のサイズが大幅に大きくなっています。これらが InnoDB テーブルであることを考えると、バッファを変更すると、このサイズのキーを処理するのに役立ちますか? これに対するさらなる更新:キーのサイズを縮小して再分析しましたが、パフォーマンスに変化はありません。

EVENT_TABLEの更新記述子:

両方のデータベースで同一であることに注意してください

+--------------------+--------------+------+-----+---------+----------------+
| Field              | Type         | Null | Key | Default | Extra          |
+--------------------+--------------+------+-----+---------+----------------+
| EVENT_TABLE_ID     | bigint(20)   | NO   | PRI | NULL    | auto_increment | 
| EVENT_TYPE         | varchar(10)  | NO   |     | NULL    |                | 
| TABLE_ID1          | int(11)      | NO   | MUL | NULL    |                | 
| TABLE_ID2          | int(11)      | YES  |     | NULL    |                | 
| TABLE_ID3          | int(11)      | YES  |     | NULL    |                | 
| TABLE_ID4          | int(11)      | YES  |     | NULL    |                | 
| EVENT_CREATED_DATE | datetime     | NO   |     | NULL    |                | 
| MESSAGE_REF        | varchar(100) | YES  |     | NULL    |                | 
+--------------------+--------------+------+-----+---------+----------------+

そして、適切な測定のために、SHOW CREATE TABLE EVENT_TABLE:

データベース間でこれが異なる唯一の点は、自動インクリメント値です

| EVENT_TABLE | CREATE TABLE `EVENT_TABLE` (
  `EVENT_TABLE_ID` bigint(20) NOT NULL AUTO_INCREMENT,
  `EVENT_TYPE` varchar(10) NOT NULL,
  `TABLE_ID1` int(11) NOT NULL,
  `TABLE_ID2` int(11) DEFAULT NULL,
  `TABLE_ID3` int(11) DEFAULT NULL,
  `TABLE_ID4` int(11) DEFAULT NULL,
  `EVENT_CREATED_DATE` datetime NOT NULL,
  `MESSAGE_REF` varchar(100) DEFAULT NULL,
  PRIMARY KEY (`EVENT_TABLE_ID`),
  KEY `IX_EVENT_ID_EVENT_TYPE` (`TABLE_ID1`,`EVENT_TYPE`)
) ENGINE=InnoDB AUTO_INCREMENT=1925 DEFAULT CHARSET=utf8 | 

誰でもこの問題を解決する方法を提案できますか? 私は何を逃したのですか?

マイケル・ホルツマンからの質問後 の更新 これは、彼の更新された STRAIGHT_JOIN クエリに基づく新しいクエリ プランです。データベース B には「Using temporary; Using filesort」がありますが、データベース A にはありません。これは、長いキーまたは同様のものが原因である可能性がありますか?

データベース A

+----+-------------+-------+--------+----------------------------------------------------------------------------------------------------------------------------------------+----------------------------------+---------+------------------------------+------+-------------+
| id | select_type | table | type   | possible_keys                                                                                                                          | key                              | key_len | ref                          | rows | Extra       |
+----+-------------+-------+--------+----------------------------------------------------------------------------------------------------------------------------------------+----------------------------------+---------+------------------------------+------+-------------+
|  1 | SIMPLE      | ps    | index  | PRIMARY,IX_ETA_DATE                                                                                                                    | PRIMARY                          | 4       | NULL                         |  168 | Using where | 
|  1 | SIMPLE      | ev0   | ref    | IX_EVENT_ID_EVENT_TYPE                                                                                                                 | IX_EVENT_ID_EVENT_TYPE           | 36      | UNIVIS_PROD.ps.ship_id,const |    1 |             | 
|  1 | SIMPLE      | ev1   | ref    | IX_EVENT_ID_EVENT_TYPE                                                                                                                 | IX_EVENT_ID_EVENT_TYPE           | 36      | UNIVIS_PROD.ps.ship_id,const |    1 |             | 
|  1 | SIMPLE      | ev2   | ref    | IX_EVENT_ID_EVENT_TYPE                                                                                                                 | IX_EVENT_ID_EVENT_TYPE           | 36      | UNIVIS_PROD.ps.ship_id,const |    1 |             | 
|  1 | SIMPLE      | ev3   | ref    | IX_EVENT_ID_EVENT_TYPE                                                                                                                 | IX_EVENT_ID_EVENT_TYPE           | 36      | UNIVIS_PROD.ps.ship_id,const |    1 |             | 
|  1 | SIMPLE      | ev4   | ref    | IX_EVENT_ID_EVENT_TYPE                                                                                                                 | IX_EVENT_ID_EVENT_TYPE           | 36      | UNIVIS_PROD.ps.ship_id,const |    1 |             | 
|  1 | SIMPLE      | ev5   | ref    | IX_EVENT_ID_EVENT_TYPE                                                                                                                 | IX_EVENT_ID_EVENT_TYPE           | 36      | UNIVIS_PROD.ps.ship_id,const |    1 |             | 
|  1 | SIMPLE      | psi   | ref    | PRIMARY,IX_po_shipment_item_po_shipment1,FK_po_shipment_item_po_shipment1                                                              | IX_po_shipment_item_po_shipment1 | 4       | UNIVIS_PROD.ps.ship_id       |    1 |             | 
|  1 | SIMPLE      | pa    | ref    | IX_po_alloc_po_shipment_item2,IX_po_alloc_po_details_old,FK_po_alloc_po_shipment1,FK_po_alloc_po_shipment_item1,FK_po_alloc_po_header1 | FK_po_alloc_po_shipment_item1    | 8       | UNIVIS_PROD.psi.UID_items    |    6 | Using where | 
|  1 | SIMPLE      | ph    | eq_ref | PRIMARY,IX_HDR_ID                                                                                                                      | PRIMARY                          | 4       | UNIVIS_PROD.pa.hdr_id        |    1 |             | 
+----+-------------+-------+--------+----------------------------------------------------------------------------------------------------------------------------------------+----------------------------------+---------+------------------------------+------+-------------+

データベースB

+----+-------------+-------+--------+----------------------------------------------------------------------------------------------------------------------------------------+----------------------------------+---------+-------------------------------+------+----------------------------------------------+
| id | select_type | table | type   | possible_keys                                                                                                                          | key                              | key_len | ref                           | rows | Extra                                        |
+----+-------------+-------+--------+----------------------------------------------------------------------------------------------------------------------------------------+----------------------------------+---------+-------------------------------+------+----------------------------------------------+
|  1 | SIMPLE      | ps    | range  | PRIMARY,IX_ETA_DATE                                                                                                                    | IX_ETA_DATE                      | 4       | NULL                          |   38 | Using where; Using temporary; Using filesort | 
|  1 | SIMPLE      | ev0   | ref    | IX_EVENT_ID_EVENT_TYPE                                                                                                                 | IX_EVENT_ID_EVENT_TYPE           | 36      | UNIVIS_DEV01.ps.ship_id,const |    1 |                                              | 
|  1 | SIMPLE      | ev1   | ref    | IX_EVENT_ID_EVENT_TYPE                                                                                                                 | IX_EVENT_ID_EVENT_TYPE           | 36      | UNIVIS_DEV01.ps.ship_id,const |    1 |                                              | 
|  1 | SIMPLE      | ev2   | ref    | IX_EVENT_ID_EVENT_TYPE                                                                                                                 | IX_EVENT_ID_EVENT_TYPE           | 36      | UNIVIS_DEV01.ps.ship_id,const |    1 |                                              | 
|  1 | SIMPLE      | ev3   | ref    | IX_EVENT_ID_EVENT_TYPE                                                                                                                 | IX_EVENT_ID_EVENT_TYPE           | 36      | UNIVIS_DEV01.ps.ship_id,const |    1 |                                              | 
|  1 | SIMPLE      | ev4   | ref    | IX_EVENT_ID_EVENT_TYPE                                                                                                                 | IX_EVENT_ID_EVENT_TYPE           | 36      | UNIVIS_DEV01.ps.ship_id,const |    1 |                                              | 
|  1 | SIMPLE      | ev5   | ref    | IX_EVENT_ID_EVENT_TYPE                                                                                                                 | IX_EVENT_ID_EVENT_TYPE           | 36      | UNIVIS_DEV01.ps.ship_id,const |    1 |                                              | 
|  1 | SIMPLE      | psi   | ref    | PRIMARY,IX_po_shipment_item_po_shipment1,FK_po_shipment_item_po_shipment1                                                              | IX_po_shipment_item_po_shipment1 | 4       | UNIVIS_DEV01.ps.ship_id       |    1 |                                              | 
|  1 | SIMPLE      | pa    | ref    | IX_po_alloc_po_shipment_item2,IX_po_alloc_po_details_old,FK_po_alloc_po_shipment1,FK_po_alloc_po_shipment_item1,FK_po_alloc_po_header1 | IX_po_alloc_po_shipment_item2    | 4       | UNIVIS_DEV01.ps.ship_id       |    3 | Using where                                  | 
|  1 | SIMPLE      | ph    | eq_ref | PRIMARY,IX_HDR_ID                                                                                                                      | PRIMARY                          | 4       | UNIVIS_DEV01.pa.hdr_id        |    1 |                                              | 
+----+-------------+-------+--------+----------------------------------------------------------------------------------------------------------------------------------------+----------------------------------+---------+-------------------------------+------+----------------------------------------------+

更新それは間違いなくデータ関連です。データベース A からデータをダンプし、次を使用してデータベース B にロードしました。

SELECT * from <table> into outfile <file>

LOAD DATA INFILE <file> into table <table>

次に、データベース B のクエリがすばやく実行されます。データベースと同じ速さ A.データの何が問題なのかを診断する方法についてのアイデアはありますか??

UPDATE @newtover: データベース A から:

+-----------------+---------------------+
| eta_selectivity | ship_id_selectivity |
+-----------------+---------------------+
|          0.0693 |              1.0000 | 
+-----------------+---------------------+
1 row in set (0.02 sec)

データベースBから(悪いもの)

+-----------------+---------------------+
| eta_selectivity | ship_id_selectivity |
+-----------------+---------------------+
|          0.1814 |              1.0000 | 
+-----------------+---------------------+
1 row in set (0.02 sec)

そして、po_shipment の show create:

| po_shipment | CREATE TABLE `po_shipment` (
  `ship_id` int(11) NOT NULL DEFAULT '0',
  `ship_type` varchar(16) DEFAULT NULL,
  `foreign_agent` varchar(16) DEFAULT NULL,
  `agent_ref` varchar(16) DEFAULT NULL,
  `exporter_code` varchar(30) DEFAULT NULL,
  `importer_code` varchar(30) DEFAULT NULL,
  `carrier_code` varchar(30) DEFAULT NULL,
  `exporter_name` varchar(50) DEFAULT NULL,
  `importer_name` varchar(50) DEFAULT NULL,
  `carrier_name` varchar(50) DEFAULT NULL,
  `receipt` varchar(30) DEFAULT NULL,
  `pol_aol` varchar(50) DEFAULT NULL,
  `pod_aod` varchar(30) DEFAULT NULL,
  `final_dest` varchar(50) DEFAULT NULL,
  `vessel_flno` varchar(30) DEFAULT NULL,
  `ets` date DEFAULT NULL,
  `eta` date DEFAULT NULL,
  `pieces` int(11) DEFAULT '0',
  `weight` decimal(17,2) DEFAULT '0.00',
  `volume` decimal(17,2) DEFAULT '0.00',
  `marks` varchar(500) DEFAULT NULL,
  `goods_desc` varchar(500) DEFAULT NULL,
  `ship_terms` varchar(16) DEFAULT NULL,
  `ship_terms_desc` varchar(50) DEFAULT NULL,
  `house_hawb` varchar(30) DEFAULT NULL,
  `ocean_mawb` varchar(30) DEFAULT NULL,
  `booking_date` date DEFAULT NULL,
  `expected_cargo` date DEFAULT NULL,
  `mfrt_jobdisp` varchar(30) DEFAULT NULL,
  `ship_complete` date DEFAULT NULL,
  `user_id` varchar(30) DEFAULT NULL,
  `receipt_desc` varchar(60) DEFAULT NULL,
  `fin_dest_desc` varchar(60) DEFAULT NULL,
  `pol_aol_desc` varchar(60) DEFAULT NULL,
  `pod_aod_desc` varchar(60) DEFAULT NULL,
  `exporter_ref` varchar(26) DEFAULT NULL,
  `carrier_ref` varchar(26) DEFAULT NULL,
  `terms_conds` date DEFAULT NULL,
  `last_amended` date DEFAULT NULL,
  `user_amended` varchar(30) DEFAULT NULL,
  `package_type` varchar(24) DEFAULT NULL,
  `ext_cancelled` tinyint(1) NOT NULL DEFAULT '0',
  `ext_goh` tinyint(1) NOT NULL DEFAULT '0',
  `ext_arrival_date` date DEFAULT NULL,
  `ext_booking_ref` varchar(255) DEFAULT NULL,
  `ext_dc_booked_delivery_date` date DEFAULT NULL,
  `ext_dc_booked_delivery_time` varchar(10) DEFAULT NULL,
  `ext_comments` text,
  `deleted` tinyint(1) NOT NULL DEFAULT '0',
  `last_amended_time` int(10) DEFAULT NULL,
  `last_amended_uni` varchar(30) DEFAULT NULL,
  PRIMARY KEY (`ship_id`),
  KEY `IX_ETA_DATE` (`eta`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 | 

UPDATE @chris_I EVENT_TABLE 以外の他のすべての結合を削除してクエリを削除すると、同じパフォーマンスが得られます (つまり、くだらない)

SELECT * FROM po_shipment ps 
LEFT JOIN EVENT_TABLE ev0 ON ev0.TABLE_ID1 = ps.ship_id AND ev0.EVENT_TYPE = 'MAS0' 
LEFT JOIN EVENT_TABLE ev1 ON ev1.TABLE_ID1 = ps.ship_id AND ev1.EVENT_TYPE = 'MAS1' 
LEFT JOIN EVENT_TABLE ev2 ON ev2.TABLE_ID1 = ps.ship_id AND ev2.EVENT_TYPE = 'MAS2' 
LEFT JOIN EVENT_TABLE ev3 ON ev3.TABLE_ID1 = ps.ship_id AND ev3.EVENT_TYPE = 'MAS3' 
LEFT JOIN EVENT_TABLE ev4 ON ev4.TABLE_ID1 = ps.ship_id AND ev4.EVENT_TYPE = 'MAS4' 
LEFT JOIN EVENT_TABLE ev5 ON ev5.TABLE_ID1 = ps.ship_id AND ev5.EVENT_TYPE = 'MAS5' 
WHERE ps.eta >= '2010-03-22'
GROUP BY ps.ship_id
LIMIT 100;

UPDATE @Marcus Adams: 内部結合を削除して要求したプランのクエリ:

SELECT * FROM po_shipment ps 
LEFT JOIN EVENT_TABLE ev0 ON ev0.TABLE_ID1 = ps.ship_id AND ev0.EVENT_TYPE = 'MAS0' 
LEFT JOIN EVENT_TABLE ev1 ON ev1.TABLE_ID1 = ps.ship_id AND ev1.EVENT_TYPE = 'MAS1' 
LEFT JOIN EVENT_TABLE ev2 ON ev2.TABLE_ID1 = ps.ship_id AND ev2.EVENT_TYPE = 'MAS2' 
LEFT JOIN EVENT_TABLE ev3 ON ev3.TABLE_ID1 = ps.ship_id AND ev3.EVENT_TYPE = 'MAS3' 
LEFT JOIN EVENT_TABLE ev4 ON ev4.TABLE_ID1 = ps.ship_id AND ev4.EVENT_TYPE = 'MAS4' 
LEFT JOIN EVENT_TABLE ev5 ON ev5.TABLE_ID1 = ps.ship_id AND ev5.EVENT_TYPE = 'MAS5' 
WHERE ps.eta >= '2010-03-22'
GROUP BY ps.ship_id
LIMIT 100;

データベース A からのクエリ プラン (0.35 秒で応答)

+----+-------------+-------+-------+------------------------+------------------------+---------+------------------------------+------+----------------------------------------------+
| id | select_type | table | type  | possible_keys          | key                    | key_len | ref                          | rows | Extra                                        |
+----+-------------+-------+-------+------------------------+------------------------+---------+------------------------------+------+----------------------------------------------+
|  1 | SIMPLE      | ps    | range | IX_ETA_DATE            | IX_ETA_DATE            | 4       | NULL                         |  174 | Using where; Using temporary; Using filesort | 
|  1 | SIMPLE      | ev0   | ref   | IX_EVENT_ID_EVENT_TYPE | IX_EVENT_ID_EVENT_TYPE | 36      | UNIVIS_PROD.ps.ship_id,const |    1 |                                              | 
|  1 | SIMPLE      | ev1   | ref   | IX_EVENT_ID_EVENT_TYPE | IX_EVENT_ID_EVENT_TYPE | 36      | UNIVIS_PROD.ps.ship_id,const |    1 |                                              | 
|  1 | SIMPLE      | ev2   | ref   | IX_EVENT_ID_EVENT_TYPE | IX_EVENT_ID_EVENT_TYPE | 36      | UNIVIS_PROD.ps.ship_id,const |    1 |                                              | 
|  1 | SIMPLE      | ev3   | ref   | IX_EVENT_ID_EVENT_TYPE | IX_EVENT_ID_EVENT_TYPE | 36      | UNIVIS_PROD.ps.ship_id,const |    1 |                                              | 
|  1 | SIMPLE      | ev4   | ref   | IX_EVENT_ID_EVENT_TYPE | IX_EVENT_ID_EVENT_TYPE | 36      | UNIVIS_PROD.ps.ship_id,const |    1 |                                              | 
|  1 | SIMPLE      | ev5   | ref   | IX_EVENT_ID_EVENT_TYPE | IX_EVENT_ID_EVENT_TYPE | 36      | UNIVIS_PROD.ps.ship_id,const |    1 |                                              | 
+----+-------------+-------+-------+------------------------+------------------------+---------+------------------------------+------+----------------------------------------------

データベース B からのクエリ プラン (お茶を淹れるのにかかる時間内に応答しない)

    +----+-------------+-------+-------+------------------------+------------------------+---------+-------------------------------+------+----------------------------------------------+
| id | select_type | table | type  | possible_keys          | key                    | key_len | ref                           | rows | Extra                                        |
+----+-------------+-------+-------+------------------------+------------------------+---------+-------------------------------+------+----------------------------------------------+
|  1 | SIMPLE      | ps    | range | IX_ETA_DATE            | IX_ETA_DATE            | 4       | NULL                          |   38 | Using where; Using temporary; Using filesort | 
|  1 | SIMPLE      | ev0   | ref   | IX_EVENT_ID_EVENT_TYPE | IX_EVENT_ID_EVENT_TYPE | 36    
4

14 に答える 14

3

クエリに STRAIGHT_JOIN を追加して、実行プランに問題があるかどうかを確認してください。オプティマイザはデータベースごとに異なる実行計画を選択しており、これが問題の原因となっている可能性があります。

SELECT STRAIGHT_JOIN * FROM po_shipment ps 
LEFT JOIN EVENT_TABLE ev0 ON ev0.TABLE_ID1 = ps.ship_id AND ev0.EVENT_TYPE = 'MAS0' 
LEFT JOIN EVENT_TABLE ev1 ON ev1.TABLE_ID1 = ps.ship_id AND ev1.EVENT_TYPE = 'MAS1' 
LEFT JOIN EVENT_TABLE ev2 ON ev2.TABLE_ID1 = ps.ship_id AND ev2.EVENT_TYPE = 'MAS2' 
LEFT JOIN EVENT_TABLE ev3 ON ev3.TABLE_ID1 = ps.ship_id AND ev3.EVENT_TYPE = 'MAS3' 
LEFT JOIN EVENT_TABLE ev4 ON ev4.TABLE_ID1 = ps.ship_id AND ev4.EVENT_TYPE = 'MAS4' 
LEFT JOIN EVENT_TABLE ev5 ON ev5.TABLE_ID1 = ps.ship_id AND ev5.EVENT_TYPE = 'MAS5' 
JOIN po_shipment_item psi USING (ship_id) 
JOIN po_alloc pa ON ps.ship_id = pa.ship_id AND pa.UID_items = psi.UID_items 
JOIN po_header ph ON pa.hdr_id = ph.hdr_id
WHERE ps.eta >= '2010-03-22'
GROUP BY ps.ship_id
LIMIT 100;

更新
1.データベース A の新しい実行計画は、主キーを使用しているため、ファイルソートまたは一時テーブルを必要としません。データベース B のクエリを高速化できるかどうかを確認するために、クエリに USE INDEX を追加し始めます。ship_id は po_shipment の主キーですか? その場合は、日付のグループ化またはフィルタリングによって、何がより多くの費用がかかるかを把握する必要があります。

SELECT STRAIGHT_JOIN * FROM po_shipment ps USE INDEX( PRIMARY )
LEFT JOIN EVENT_TABLE ev0 ON ev0.TABLE_ID1 = ps.ship_id AND ev0.EVENT_TYPE = 'MAS0' 
LEFT JOIN EVENT_TABLE ev1 ON ev1.TABLE_ID1 = ps.ship_id AND ev1.EVENT_TYPE = 'MAS1' 
LEFT JOIN EVENT_TABLE ev2 ON ev2.TABLE_ID1 = ps.ship_id AND ev2.EVENT_TYPE = 'MAS2' 
LEFT JOIN EVENT_TABLE ev3 ON ev3.TABLE_ID1 = ps.ship_id AND ev3.EVENT_TYPE = 'MAS3' 
LEFT JOIN EVENT_TABLE ev4 ON ev4.TABLE_ID1 = ps.ship_id AND ev4.EVENT_TYPE = 'MAS4' 
LEFT JOIN EVENT_TABLE ev5 ON ev5.TABLE_ID1 = ps.ship_id AND ev5.EVENT_TYPE = 'MAS5' 
JOIN po_shipment_item psi USING (ship_id) 
JOIN po_alloc pa ON ps.ship_id = pa.ship_id AND pa.UID_items = psi.UID_items 
JOIN po_header ph ON pa.hdr_id = ph.hdr_id
WHERE ps.eta >= '2010-03-22'
GROUP BY ps.ship_id
LIMIT 100;

それでも解決しない場合は、データベース B のデータベース A の実行計画で使用されているインデックスをさらに提案してみてください。

于 2010-03-31T03:35:57.587 に答える
2

それがデータの問題である場合、正確な問題が何であるかはわかりませんが、この種の問題を解決するための私のお気に入りの戦略は次のとおりです。

結合の半分を削除してみてください。クエリが高速に実行されるまで、再帰的に繰り返します。次に、最後の手順で削除した結合の半分を追加します... (この戦略では、結合ごとに結合を削除して追加するよりもはるかに少ない手順で済みます)。

「悪い」結合を見つけたら、クエリが再び高速に実行されるまで、追加の「where」句でその値を制限してみてください...各ステップで、常に問題を半分に減らすようにしてください。

注: データベース B のデータの合計量が少なくても、結合の中間結果についてより多くのレコードを取得する場合がよくあります。

于 2010-04-06T17:06:28.653 に答える
2

しばらくMySQLに触れていませんが、問題はどちらかに関係していると思います

  1. キー/結合フィールドの長さ (実際のデータ) を確認しましたか? sort_buffer が大きな (サイズの) キーで結合するディスクにページングする可能性がありますか? (これはデータの問題のようなにおいがします...)
  2. サーバー設定は、基本的にメモリ内の一時テーブルに書き込んでいます。数年前に似たようなことがありました。key_buffer_size、table_cache、read_rnd_buffer_size、sort_buffer、read_buffer_size を拡大して、それが役立つかどうかを確認しましたか?
于 2010-03-31T00:50:56.027 に答える
1

レンジセレクターless than<とgreater than>を使用するときにも同じことを経験しました。

実験:範囲が大きすぎない場合は、範囲を拡大してIN(...、...、...)ステートメントをインストールしようとしましたか?

例えば

SELECT * FROM po_shipment ps USE INDEX (IX_ETA_DATE)
JOIN po_shipment_item psi USING (ship_id) 
JOIN po_alloc pa ON ps.ship_id = pa.ship_id AND pa.UID_items = psi.UID_items 
JOIN po_header ph ON pa.hdr_id = ph.hdr_id 
LEFT JOIN EVENT_TABLE ev0 ON ev0.TABLE_ID1 = ps.ship_id AND ev0.EVENT_TYPE = 'MAS0' 
LEFT JOIN EVENT_TABLE ev1 ON ev1.TABLE_ID1 = ps.ship_id AND ev1.EVENT_TYPE = 'MAS1' 
LEFT JOIN EVENT_TABLE ev2 ON ev2.TABLE_ID1 = ps.ship_id AND ev2.EVENT_TYPE = 'MAS2' 
LEFT JOIN EVENT_TABLE ev3 ON ev3.TABLE_ID1 = ps.ship_id AND ev3.EVENT_TYPE = 'MAS3' 
LEFT JOIN EVENT_TABLE ev4 ON ev4.TABLE_ID1 = ps.ship_id AND ev4.EVENT_TYPE = 'MAS4' 
LEFT JOIN EVENT_TABLE ev5 ON ev5.TABLE_ID1 = ps.ship_id AND ev5.EVENT_TYPE = 'MAS5' 
WHERE ps.eta IN ('2010-03-22','2010-03-21','2010-03-20',...)
GROUP BY ps.ship_id
LIMIT 100;

編集:Salman Aが提案したように、USE INDEX()ヒントを追加しました。mysql seeの可能なインデックスのようですが、それを使用しないことを選択しました...テストする価値があります。

于 2010-04-12T16:18:43.500 に答える
1

まず、適切なフィールドにインデックスを作成したことを確認してください。私はあなたがそれをしたと確信しています。

次に、インデックスヒント(USE INDEX)を使用して、データベースにインデックスを適切に使用させるようにします。

同様の問題が発生し、インデックスがmysqlによって適切に設定および使用されていると想定しましたが、そうではありませんでした。インデックスヒントを使用して回避することができました。

于 2010-04-07T10:20:03.137 に答える
1

「CHECK TABLE」や「OPTIMIZE TABLE」を試してみる必要がありますか?

キーインデックスが適切に更新されず、CHECK TABLEを実行するとそれらが修正されるという問題が発生した同様の状況がありました。ロングショットですが、試してみる価値があります。

于 2010-04-07T09:53:53.433 に答える
1

それは InnoDB であるため、おそらくロックの問題のようです。同時に何が起こっているのでしょうか?

于 2010-03-31T03:03:29.420 に答える
1

統計を更新します。かつて同様の問題がありましたが、これは私にとってはうまくいきます。

于 2010-03-30T22:33:50.390 に答える
1

目立った赤字を引き起こしているのは、GROUP BY句の手動ソート(ファイルソート)である可能性があると思います。

SQL_BIG_RESULT ヒントを使用して、MySQL が GROUP BY の処理方法を改善するかどうかを確認してください。

SELECT SQL_BIG_RESULT * FROM ...
于 2010-04-12T17:27:06.813 に答える
1

po_shipment.eta と po_shipment.ship_id のデータの選択性は何ですか。両方のデータベースから次のクエリの結果を投稿していただけますか:

SELECT
    count(distinct eta)/count(*) as eta_selectivity,
    count(distinct ship_id)/count(*) as ship_id_selectivity
FROM po_shipment;

通常、フィールド データがより選択的であるほど (1 に近いほど)、より適切なインデックスが機能しています。オプティマイザーが必要な統計を欠いている場合、po_shipment.eta 内のデータの分散が非常に不均一である可能性もあります ('2099-01-01' などを特別な値として使用する場合)。

ところで、SHOW CREATE TABLE po_shipment を提供してもらえますか? テーブルのインデックスは、いくつかの光を当てる可能性があります。

UPD : フィールドの選択性がフィールドのように低い場合eta、インデックスは基本的に役に立ちません。さらに悪いことに、選択時にオプティマイザが混乱し、データの挿入と更新が遅くなる可能性があります。

最初の提案は、フィールドのインデックスを削除しetaて結果を測定することです。A データベースのオプティマイザーは、選択性が非常に低いためにインデックスを使用しようとさえせず、B データベースの場合はインデックスを使用しようとする可能性があります。

私を悩ませている 2 番目のことは、なぜ最初に ship_id でグループ化するのですか? 暗黙的な一時テーブルに必要があり、フィールドの中に TEXT (あなたの場合のように) または BLOB がある場合、MySQL は常に並べ替えのためにディスク一時テーブルを使用します (これは GROUP BY で暗黙的に必要です)。あなたの場合、ship_id はクラスター化された主キーであり、結果はいずれにせよ ship_id でソートされます。必要なのは、ベース クエリ (複数の一致が存在する可能性がある場合は、ship_id によって既にグループ化されている) を抽出し、範囲条件を適用し、上部で group by を使用しないベース クエリで JOIN po_shipment することです。

そして3番目。先頭に * を使用する場合、すべてのフィールドが本当に必要ですか? 10 のテーブルに参加すると、多くのフィールドを受け取ります。それらすべてが必要だとはほとんど信じられません。結果から TEXT フィールドを除外しても、クエリのパフォーマンスが向上する場合があります。

于 2010-04-07T19:37:28.443 に答える
1

データに問題があるように思われるので、問題の原因となっているデータを特定することはおそらく役立つでしょう。3 番目のデータベース C を作成し、データベース B からのデータの半分を 2 回挿入します (行数が同じになるようにします)。データベース C が遅い場合は、不良データが存在します。それ以外の場合は、残りの半分になります。問題のデータを見つけるのに役立つように、チャンク サイズを小さくして繰り返します。

データベース B はデータベース A よりも小さいですが、テーブル 'po_header' と 'EVENT_TABLE' は比例して小さくはありません。それは速度の違いと関係があるかもしれません。

于 2010-04-06T17:45:36.387 に答える
0

私はあなたがこれを間違った方法で行っていると思います。LEFT JOIN を実行すると、po_shipment との一致に関係なく、EVENT_TABLE のすべてのレコードが返されます。

そして、EVENT_TABLE への LEFT JOIN を 6 回実行しました。すべてのクエリで (6 * (SELECT count(*) FROM EVENT_TABLE) ) レコードを取得しています。データベース A はデータベース B よりもレコード数が少ないため、クエリはもちろん A の方が高速に実行されます。

私は、このようなものが世界をより良く実行すると思います:

DECLARE @TEMP_EVENT_TYPES table 
(
    EVENT_TYPE varchar(10) PRIMARY KEY
)
;
/*
INSERT VALUES 'MAS0', 'MAS1', 'MAS2', 'MAS3', 'MAS4', 'MAS5'
*/

;
SELECT * FROM po_shipment ps 
JOIN po_shipment_item psi USING (ship_id) 
JOIN po_alloc pa ON ps.ship_id = pa.ship_id AND pa.UID_items = psi.UID_items 
JOIN po_header ph ON pa.hdr_id = ph.hdr_id 
INNER JOIN 
    EVENT_TABLE et ON et.TABLE_ID1 = ps.ship_id
INNER JOIN 
    @TEMP_EVENT_TYPES tet ON tet.event_type = et.EVENT_TYPE
WHERE ps.eta >= '2010-03-22'
GROUP BY ps.ship_id
于 2010-04-06T18:18:41.220 に答える
0

好奇心から - B の元のデータには多くの NULL がありますか?

于 2010-04-13T08:25:33.617 に答える
0

状態遷移ごとに event_table のイベント レコードを使用して、po_shipment の状態マシンをモデリングしているように見えます。

このクエリで表現しようとしているビジネス ロジックは何ですか?

これを達成するには、状態フィールドを po_shipment に追加できるはずです。これにより、一連のイベントが event_table に要約され、非正規化されます。

特定のレコードに対して 6 つのイベントすべてが発生したことを確認するロジックを構築することは、データベースにあるべきではなく、モデルにあり、データベースに永続化されている必要があります (モデルのクラシック ステート マシン パターン)。

次に、状態 = 'MAS5' および eta > date; の po_shipment から選択するだけです。

于 2010-04-13T02:22:59.767 に答える