2017-11-09 12 views
0

私は遠くのMySQL DBに3つのテーブルを結合したSQLクエリを持っています - これらのテーブルのうち2つは約18GByte(STEP_RESULTとmeas_numericlimit)のサイズを持ち、遠いサーバはTMPテーブルを作成します年齢(約25分)から終了まで このクエリを最適化するにはどうすればよいですか?ここではSHOW TABLESの 大きなテーブルでMySQLクエリを最適化する

select 
    t1.UUT_NAME, 
    t1.STATION_NUM, 
    t1.START_DATE_TIME, 
    t3.LOW_LIMIT, 
    t3.DATA, 
    t3.HIGH_LIMIT, 
    t3.UNITS, 
    t2b.STEP_NAME 
from 
    meas_numericlimit t3 
     inner join STEP_RESULT t2a on t3.ID = t2a.STEP_ID 
     inner join STEP_RESULT t2b on t2a.STEP_PARENT = t2b.STEP_ID 
     inner join uut_result t1 on t2b.UUT_RESULT = t1.ID 
where 
    t1.UUT_NAME like 'Variable1-1%' and 
    t1.STATION_NUM = 'variable2' and 
    t2b.STEP_NAME = 'variable3' and 
    t2b.STEP_TYPE = 'constant' 

とEXPLAIN出力クエリ:

+--------------------+ 
| Tables_in_spectrum | 
+--------------------+ 
| cal_dates   | 
| calibrage   | 
| execution_time  | 
| meas_numericlimit | 
| station_feature | 
| step_callexe  | 
| step_graph   | 
| step_msgjnl  | 
| step_msgpopup  | 
| step_passfail  | 
| step_result  | 
| step_seqcall  | 
| step_stringvalue | 
| syst_event   | 
| uptime    | 
| users    | 
| uut_result   | 
+--------------------+ 

ここ
+----+-------------+-------+--------+-------------------------+---------+ 
| id | select_type | table | type | possible_keys   | key  | 
+----+-------------+-------+--------+-------------------------+---------+ 
| 1 | SIMPLE  | t2a | ALL | NULL     | NULL | 
| 1 | SIMPLE  | t3 | eq_ref | PRIMARY     | PRIMARY | 
| 1 | SIMPLE  | t2b | ALL | NULL     | NULL | 
| 1 | SIMPLE  | t1 | eq_ref | PRIMARY,FK_uut_result_1 | PRIMARY | 
+----+-------------+-------+--------+-------------------------+---------+ 

---------+----------------------+----------- +---------------------------+ 
key_len | ref     | rows | Extra      | 
---------+----------------------+----------- +---------------------------+ 
NULL | NULL     | 48120004 |       | 
40  | spectrum.t2a.STEP_ID |  1 |       | 
NULL | NULL     | 48120004 | Using where; Using join 
                   buffer | 
40  | spectrum.t2b.UUT_RESULT |  1 | Using where    | 
    -------+----------------------+------------+---------------------------+ 

SHOW CREATE TABLE:

CREATE TABLE `uut_result` (
    `ID` varchar(38) NOT NULL DEFAULT '', 
    `STATION_NUM` varchar(255) DEFAULT NULL, 
    `SOFTVER_ODTGEN` varchar(10) DEFAULT NULL, 
    `HARDVER_ODTGEN` varchar(10) DEFAULT NULL, 
    `NEXT_CAL_DATE` date DEFAULT NULL, 
    `UUT_NAME` varchar(255) DEFAULT NULL, 
    `UUT_SERIAL_NUMBER` varchar(255) DEFAULT NULL, 
    `UUT_VERSION` varchar(255) DEFAULT NULL, 
    `USER_LOGIN_NAME` varchar(255) DEFAULT NULL, 
    `USER_LOGIN_LOGIN` varchar(255) NOT NULL DEFAULT '', 
    `START_DATE_TIME` datetime DEFAULT NULL, 
    `EXECUTION_TIME` float DEFAULT NULL, 
    `UUT_STATUS` varchar(255) DEFAULT NULL, 
    `UUT_ERROR_CODE` int(11) DEFAULT NULL, 
    `UUT_ERROR_MESSAGE` varchar(1023) DEFAULT NULL, 
    `PAT_NAME` varchar(255) NOT NULL DEFAULT '', 
    `PAT_VERSION` varchar(10) NOT NULL DEFAULT '', 
    `TEST_LEVEL` varchar(50) DEFAULT NULL, 
    `INTERFACE_ID` int(10) unsigned NOT NULL DEFAULT '0', 
    `EXECUTION_MODE` varchar(45) DEFAULT NULL, 
    `LOOP_MODE` varchar(45) DEFAULT NULL, 
    `STOP_ON_FAIL` tinyint(4) unsigned NOT NULL DEFAULT '0', 
    `EXECUTION_COMMENT` text, 
    PRIMARY KEY (`ID`), 
    KEY `FK_uut_result_1` (`STATION_NUM`) 
) ENGINE=MyISAM DEFAULT CHARSET=latin; 

CREATE TABLE `meas_numericlimit` (
    `ID` varchar(38) NOT NULL DEFAULT '', 
    `STEP_RESULT` varchar(38) NOT NULL DEFAULT '', 
    `NAME` varchar(255) DEFAULT NULL, 
    `COMP_OPERATOR` varchar(30) DEFAULT NULL, 
    `HIGH_LIMIT` double DEFAULT NULL, 
    `LOW_LIMIT` double DEFAULT NULL, 
    `UNITS` varchar(255) DEFAULT NULL, 
    `DATA` double DEFAULT NULL, 
    `STATUS` varchar(255) DEFAULT NULL, 
    `FORMAT` varchar(15) DEFAULT NULL, 
    `NANDATA` int(11) DEFAULT '0', 
    PRIMARY KEY (`ID`), 
    KEY `FK_meas_numericlimit_1` (`STEP_RESULT`) 
) ENGINE=MyISAM DEFAULT CHARSET=latin1 

CREATE TABLE `step_result` (
    `ID` varchar(38) NOT NULL DEFAULT '', 
    `UUT_RESULT` varchar(38) NOT NULL DEFAULT '', 
    `STEP_PARENT` varchar(38) DEFAULT NULL, 
    `STEP_NAME` varchar(255) DEFAULT NULL, 
    `STEP_ID` varchar(38) NOT NULL DEFAULT '', 
    `STEP_TYPE` varchar(255) DEFAULT NULL, 
    `STATUS` varchar(255) DEFAULT NULL, 
    `REPORT_TEXT` text, 
    `DIAG` text, 
    `ERROR_OCCURRED` tinyint(1) NOT NULL DEFAULT '0', 
    `ERROR_CODE` int(11) DEFAULT NULL, 
    `ERROR_MESSAGE` varchar(1023) DEFAULT NULL, 
    `MODULE_TIME` float DEFAULT NULL, 
    `TOTAL_TIME` float DEFAULT NULL, 
    `NUM_LOOPS` int(11) DEFAULT NULL, 
    `NUM_PASSED` int(11) DEFAULT NULL, 
    `NUM_FAILED` int(11) DEFAULT NULL, 
    `ENDING_LOOP_INDEX` int(11) DEFAULT NULL, 
    `LOOP_INDEX` int(11) DEFAULT NULL, 
    `INTERACTIVE_EXENUM` int(11) DEFAULT NULL, 
    `STEP_GROUP` varchar(30) DEFAULT NULL, 
    `STEP_INDEX` int(11) DEFAULT NULL, 
    `ORDER_NUMBER` int(11) DEFAULT NULL, 
    PRIMARY KEY (`ID`), 
    KEY `FK_step_result_1` (`UUT_RESULT`), 
    KEY `IDX_step_parent` (`STEP_PARENT`) 
) ENGINE=MyISAM DEFAULT CHARSET=latin 

join_buffer_sizeの値であり、どのようなあなたの助け

+0

申し訳ありません18ギガバイト –

+1

クエリの最適化に関する質問をするときは、常にクエリの各テーブルの 'SHOW CREATE TABLE'の出力とクエリの' EXPLAIN'の出力を含めてください。テーブルの定義、カラム、インデックス、制約などを知る必要があります。 –

+0

そして、スクリーンショットではありません。テキストだけでお願いしますので、コピーしてサンドボックスでテストすることができます。 –

答えて

0

をいただき、ありがとうございますか!それはRAMの約1%を超えてはいけません。それがはるかに大きい場合は、スワッピングの危険性があります。これはパフォーマンスにとって特に悪いことです。

EXPLAINNULL | 48120004には、次のようなものがあります。INDEX(STEP_ID);

ただし、SELECTEXPLAINは一致していないようです。ダブルチェックしてください。

uut_resultINDEX(station_num, uut_name)がこの順番に必要です。ちょうど(station_num)を置き換えます。

varchar(38)とは何ですか? UUIDは36だけです。IPv6が必要です。39.

データがキャッシュするには大きすぎる場合、UUIDは非常に効率が悪いです。さらに議論する:http://mysql.rjweb.org/doc.php/uuid

多くのデータ型が縮小する可能性があります。この縮小はI/Oを削減し、クエリを高速化します。いくつかの典型的な列に対していくつかのサンプル値を提供する場合、私はより多くのアドバイスを与えることができます。

たとえば、STATUSは(通常)少数の異なる値です。これは、1バイトのENUMまたは1バイトのTINYINTとして表すことができます。おそらくあなたのアプリは数百の異なるステータス値を持っていますか?もしそうなら、それを "正常化する"方が良い答えかもしれません。

DOUBLEは8バイトです。 FLOATは4バイトしか必要としませんが、精度は〜7桁に制限されます。

(おそらくあなたはlatinlatin1を意図していない?)

またInnoDBテーブルへの切り替えを検討してください。

どのくらいのRAMがありますか?どのくらいの大きさ(GB)のテーブルですか?

+0

@trayvoujba - たとえば、私はすぐにUUIDまたはIPアドレスを認識します。 –

+0

"いくつかの典型的な列に対していくつかのサンプル値を提供すれば、私はもっとアドバイスを与えることができます。" - たとえば、step_result.STEP_IDは "{ac47980b-af6a-4e1b-b622-0a82d28d567c}"で、step_result.STEP_PARENT、step_result.UUT_RESULT、uut_result.ID、meas_numericlimit.IDの同じフォーマット これらの列はアドレスを表していませんが、ユニークなキーのようなアプリで使用されています –

+0

これは「タイプ4」のため、ランダムです。 'key_buffer_size'の値は何ですか? I/Oバウンドにならないようにするには、64GB以上のRAMと、その「可変」の設定が必要です。ここでも、データ型を縮小すると役立ちます。 UUIDを16バイト(38から)に縮小する方法については私のリンクを参照してください。しかし、4バイトの 'INT UNSIGNED'はさらに小さくなります(現実的ではないかもしれませんが)。 –

関連する問題