2017-11-09 7 views
0

나는 먼 MySQL DB에 조인 된 3 개의 테이블을 가진 SQL 쿼리를 가지고 있습니다.이 테이블 중 2 개는 약 18GByte (STEP_RESULT 및 meas_numericlimit) 크기를 가지고 있으며, 먼 서버는 나이 (약 25 분) 끝까지 어떻게이 쿼리를 최적화 할 수 있습니까? 여기서 표시 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' 

하고 설명 출력 질의 :

+--------------------+ 
| 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    | 
    -------+----------------------+------------+---------------------------+ 

표시 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 

당신의 도움이

+0

죄송합니다. 18 기가 바이트 –

+1

쿼리 최적화에 대한 질문은 항상 쿼리의 각 테이블에 대해 'SHOW CREATE TABLE'출력을 포함하고 쿼리에 대해 'EXPLAIN'출력을 포함하십시오. 우리는 테이블 정의, 컬럼, 인덱스, 제약 등을 알아야합니다. 우리가 당신을 도울 수 있도록 도와주세요! –

+0

그리고 스크린 샷이 아닌 *주십시오. 그냥 텍스트로 보내 주시면 샌드 박스에서 복사하고 테스트 할 수 있습니다. –

답변

0

join_buffer_size의 가치는 무엇인가 주셔서 감사합니다? RAM의 약 1 %를 넘지 않아야합니다. 크기가 훨씬 커지면 스와핑 위험이 발생합니다. 이는 특히 성능에 좋지 않습니다.

EXPLAIN : NULL | 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

많은 수의 데이터 유형이 수축 될 수 있습니다 (수축 될 수 있음).이 축소로 인해 입출력이 줄어들어 쿼리 속도가 빨라집니다. 일부 일반적인 열에 대해 몇 가지 샘플 값을 제공하면 더 많은 조언을 드릴 수 있습니다.

예를 들어, STATUS은 (일반적으로) 작은 값의 고유 값입니다. 이는 1 바이트의 ENUM 또는 1 바이트의 TINYINT으로 나타낼 수 있습니다. 하지만 앱에 수백 가지의 상태 값이있을 수 있습니다. 그렇다면 "정상화"가 더 나은 대답 일 수 있습니다.

DOUBLE은 8 바이트를 사용합니다. FLOAT은 4 바이트 만 사용하지만 정확도는 ~ 7 자리로 제한됩니다.

은 (아마도 당신은 latin1을 의미하지 latin?)

는 또한 이노 로의 전환을 고려해야.

얼마나 많은 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이 필요하고 그 'VARIABLE'에 대한 더 큰 설정이 필요할 수 있습니다. 데이터 유형을 줄이면 도움이됩니다. UUID를 16 바이트 (38 개)로 축소하는 방법은 내 링크를 참조하십시오. 그러나 4 바이트 'INT UNSIGNED'는 훨씬 작습니다 (현재는 실용적이지는 않지만). –