2016-07-11 3 views
1

저는 2.5million 행으로 커지고 커지는 MySQL 데이터베이스 테이블을 가지고 있습니다. 쿼리 속도를 높이기 위해 하나의 열에 인덱스를 추가했습니다. 인덱스를 수동으로 설정하면, 예를 들어 PHPMyAdmin을 통해 카디널리티가 약 1500 정도가되고 내 쿼리가 문제없이 실행됩니다.MySQL 테이블 인덱스 카디널리티

그런 다음 몇 가지 쿼리 (특히 INSERT가 있지만 이에 국한되지 않음)가 실행 된 후 해당 인덱스의 카디널리티가 17 또는 18로 떨어지고 쿼리가 매우 느리게 실행 된 후에 문제가 발생합니다. 때로는 약 1500으로 돌아가는 것처럼 보이거나 PHPMyAdmin을 통해 다시해야합니다.

이 카디널리티 삭제가 중단되는 것을 막을 수있는 방법이 있습니까?

CREATE TABLE IF NOT EXISTS `probe_results` (
    `probe_result_id` int(11) NOT NULL AUTO_INCREMENT, 
    `date` date NOT NULL, 
    `month` int(11) NOT NULL, 
    `year` int(11) NOT NULL, 
    `time` time NOT NULL, 
    `type` varchar(11) NOT NULL, 
    `probe_id` varchar(50) NOT NULL, 
    `status` varchar(11) NOT NULL, 
    `temp_1` decimal(11,0) NOT NULL, 
    `temp_2` decimal(11,0) NOT NULL, 
    `crc` varchar(11) NOT NULL, 
    `raw_data` text NOT NULL, 
    `txt_file` text NOT NULL, 
    PRIMARY KEY (`probe_result_id`), 
    KEY `probe_id` (`probe_id`) 
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=2527300 ; 

'probe_result_id'열이 기본 키이고, probe_id가 해당 색인이있는 열입니다.

예 질의 : 당신이 떨어지는 것을 방지하기위한 직접적인 수단이되지 않도록

SELECT IF(b.reactive_total IS NULL, 0, b.reactive_total) AS reactive_total, a.* FROM (SELECT COUNT(CASE WHEN asset_testing_results.asset_testing_year = '2016' AND asset_testing_results.asset_testing_month = '7' AND asset_testing_results.asset_stopped = '0' AND asset_testing_results.asset_testing_completed = '0' THEN 1 END) AS due_total, (COUNT(CASE WHEN asset_testing_results.asset_testing_year = '2016' AND asset_testing_results.asset_stopped = '0' AND asset_testing_results.asset_testing_completed = '1' AND asset_testing_results.asset_testing_satisfactory = '1' AND asset_testing_results.asset_testing_actioned = '0' THEN 1 END)+(IF(probes_passed_total IS NULL, 0, probes_passed_total))) AS passed_total, (COUNT(CASE WHEN asset_testing_results.asset_testing_year = '2016' AND asset_testing_results.asset_stopped = '0' AND asset_testing_results.asset_testing_completed = '1' AND asset_testing_results.asset_testing_satisfactory = '0' AND asset_testing_results.asset_testing_actioned = '0' THEN 1 END)+(IF(probes_failed_total IS NULL, 0, probes_failed_total))) AS failed_total, COUNT(CASE WHEN asset_testing_results.asset_testing_year = '2016' AND asset_testing_results.asset_stopped = '0' AND asset_testing_results.asset_testing_completed = '1' AND asset_testing_results.asset_testing_actioned = '1' THEN 1 END) AS actioned_total, COUNT(CASE WHEN asset_testing_results.asset_testing_year = '2016' AND asset_testing_results.asset_testing_month < '7' AND asset_testing_results.asset_testing_completed = '0' AND asset_testing_results.asset_testing_satisfactory = '0' AND asset_testing_results.asset_stopped = '0' THEN 1 END) AS missed_total, site.site_key, site.site_name FROM site LEFT JOIN location ON location.site_key = site.site_key LEFT JOIN sub_location ON sub_location.location_key = location.location_key LEFT JOIN asset ON asset.sub_location_key = sub_location.sub_location_key AND asset.stopped = '0' LEFT JOIN asset_testing ON asset_testing.asset_type_key = asset.asset_type_key AND asset_testing.probe_assessed = '0' LEFT JOIN asset_testing_results ON asset_testing_results.asset_testing_key = asset_testing.asset_testing_key AND asset_testing_results.asset_key = asset.asset_key LEFT JOIN (SELECT site.site_key, COUNT(CASE WHEN p.probe_id IS NOT NULL AND p.asset_testing_key IS NOT NULL THEN 1 END) AS probes_passed_total, COUNT(CASE WHEN p.probe_id IS NOT NULL AND p.asset_testing_key IS NULL AND p.temp_1 IS NOT NULL THEN 1 END) AS probes_failed_total FROM assetsvs_probes LEFT JOIN (SELECT q.probe_id, q.month, q.year, IF(r.temp_1 IS NULL, q.temp_1, r.temp_1) as temp_1, r.asset_testing_key FROM (SELECT DISTINCT probe_results.probe_id, probe_results.month, probe_results.year, probe_results.temp_1 FROM probe_results LEFT JOIN assetsvs_probes ON assetsvs_probes.probe_id = probe_results.probe_id LEFT JOIN asset ON asset.asset_key = assetsvs_probes.asset_key LEFT JOIN sub_location ON sub_location.sub_location_key = asset.sub_location_key LEFT JOIN location ON location.location_key = sub_location.location_key LEFT JOIN site ON site.site_key = location.site_key WHERE site.client_key = '25')q LEFT JOIN (SELECT probe_results.month, probe_results.year, probe_results.probe_id, temp_1, asset_testing.asset_testing_key FROM probe_results LEFT JOIN assetsvs_probes ON assetsvs_probes.probe_id = probe_results.probe_id LEFT JOIN asset_testing ON asset_testing.asset_testing_key = assetsvs_probes.asset_testing_key LEFT JOIN asset ON asset.asset_key = assetsvs_probes.asset_key LEFT JOIN sub_location ON sub_location.sub_location_key = asset.sub_location_key LEFT JOIN location ON location.location_key = sub_location.location_key LEFT JOIN site ON site.site_key = location.site_key WHERE temp_1 != 'invalid' AND ((temp_1 >= test_min AND test_max = '') OR (temp_1 <= test_max AND test_min = '') OR (temp_1 >= test_min AND temp_1 <= test_max)) AND year = '2016' AND site.client_key = '25' GROUP BY probe_results.month, probe_results.year, probe_results.probe_id)r ON r.probe_id = q.probe_id AND r.month = q.month AND r.year = q.year WHERE q.year = '2016' GROUP BY probe_id, month, year) p ON p.probe_id = assetsvs_probes.probe_id LEFT JOIN asset_testing ON asset_testing.asset_testing_key = assetsvs_probes.asset_testing_key LEFT JOIN asset ON asset.asset_key = assetsvs_probes.asset_key LEFT JOIN sub_location ON sub_location.sub_location_key = asset.sub_location_key LEFT JOIN location ON location.location_key = sub_location.location_key LEFT JOIN site ON site.site_key = location.site_key GROUP BY site.site_key) probe_results ON probe_results.site_key = site.site_key WHERE site.client_key = '25' GROUP BY site.site_key)a LEFT JOIN (SELECT COUNT(CASE WHEN jobs.status = '3' THEN 1 END) AS reactive_total, site.site_key FROM jobs LEFT JOIN jobs_meta ON jobs_meta.job_id = jobs.job_id AND jobs_meta.meta_key = 'start_date' LEFT JOIN site ON site.site_key = jobs.site_key WHERE site.client_key = '25' AND jobs_meta.meta_value LIKE '%/2016 %' GROUP BY site.site_key)b ON b.site_key = a.site_key 

감사 (다른 통계와 함께)

+0

에 'EXPLAIN'을 사용하여 귀하의 검색어에 대해서도 설명되어 있습니다. – Martin

+0

테이블에 13 개의 열이 있습니다.고유 ID 열에 기본 키가 있고 문제를 일으키는 것으로 보이는 두 번째 인덱스가 있습니다. – Ian

+0

네, 질문을 편집하고 테이블 열 속성의 'CREATE TABLE '목록을 출력 할 수 있습니까? 색인을 표시 할 색인을 지정 하시겠습니까? – Martin

답변

2

카디널리티가 자동으로 MySQL이 계산 및 업데이트됩니다.

그러나이 문제가 발생하지 않도록 조치를 취하거나 문제를 해결할 수 있습니다.

우선, analyze table 명령을 실행하면 MySQL은 지원되는 모든 테이블 엔진에 대한 인덱스 통계를 업데이트합니다.

innodb 테이블 엔진의 경우, MySQL은 샘플링의 동작에 영향을 줄 수있는 일련의 구성 설정을 제공합니다. 설정과 그 효과는 MySQL의 설명서에 설명되어 있습니다 : 1 또는 2가 될 수 있습니다와 같은 작은 값 •

:

주요 설정은 innodb_stats_transient_sample_pages입니다 카디널리티가 부정확합니다.

• innodb_stats_transient_sample_pages 값을 늘리면 에 더 많은 디스크 읽기가 필요할 수 있습니다. 값이 8보다 훨씬 큰 경우 (예 : 100) 테이블을 여는 데 걸리는 시간이 크게 줄어들거나 이 SHOW TABLE STATUS를 실행할 수 있습니다. 최적화 •

인덱스 선택

의 다른 추정에 따라 매우 다른 쿼리 계획을 선택할 수 있습니다.

myisam의 경우 MySQL dos는 다양한 설정을 제공하지 않습니다. myisam_stats_method 설정은 the general index statistics documentation