2010-08-16 3 views
5

다음과 같은 시나리오를 가지고 있습니다 : MySQL 데이터베이스에서 2 개의 MyISAM 테이블, 하나는 420 만 개의 행, 또 하나는 3200000 개의 행이 있습니다. 다음은 테이블에 대한 스키마입니다 :EXPLAIN이 좋은 계획을 보여 주더라도 MySQL의 느린 쿼리가

표 (4.2M 행)

F1 INTEGER UNSIGNED NOT NULL PRIMARY KEY 
f2 varchar(40) 
f3 varchar(40) 
f4 varchar(40) 
f5 varchar(40) 
f6 smallint(6) 
f7 smallint(6) 
f8 varchar(40) 
f9 varchar(40) 
f10 smallint(6) 
f11 varchar(10) 
f12 tinyint(4) 
f13 smallint(6) 
f14 text 

표 2 (320M 행)

F1 INTEGER UNSIGNED NOT NULL PRIMARY KEY 
f2 INTEGER UNSIGNED NOT NULL 

표 2는 다른 데이터베이스에 있지만 나는이 저장 사용하고 두 테이블을 쿼리하는 프로 시저 두 테이블 사이의 관계는 Table1.F1의 경우 대략 최대 일 수 있습니다. 일치하는 Table2.F1 (외래 키)의 100 개 행과 일치하는 키에 대해 Table2.f2의 값이 반환됩니다. 난 (F3 (10) (15) F2)하기 표 1에 및 표 인덱스 IX2 (F1, F2)과 IX3 (F2) 2

내가 실행하고 쿼리가되는 인덱스 IX1 있습니다

SELECT g.F1 
FROM DB1.Table1 g 
INNER JOIN DB2.Table2 gp ON g.F1 = gp.F1 
WHERE (gp.f2 = 452677825) AND 
(g.f2 = 'A string value') LIMIT 0,56 

이 쿼리는 때때로 매우 (< 1 초) 빠르지 만 g.F2도 이상 11 때로는 30 초 걸릴 쿼리에 리드와 비교되는 문자열 값을 변경합니다. 나는 이것이 왜 그렇게되는지 이해할 수 없다. 다음은 실행 된 SELECT에 대한 EXPLAIN의 결과입니다.

1, 'SIMPLE', 'g', 'ref', 'PRIMARY,IX1', 'IX1', '17', 'const', 901, 'Using where' 
1, 'SIMPLE', 'gp', 'ref', 'IX3,IX2', 'IX2', '8', 'DB1.g.F1,const', 1, 'Using index' 

꽤 좋은 실행 계획 인 것 같습니다. 설명의 맨 위 행에있는 행 수는 최대 2000 개이지만, 결과를 리턴하는 데 몇 초보다 더 오래 걸리는 이유는 모르겠다. 또한 쿼리에서 프로파일 러를 실행하고 "데이터 전송 중"단계에서 쿼리가 99.9 %를 소비하고 있음을 확인했습니다. 누구나 이것이 왜 그렇게하고, 쿼리를 최적화하기 위해 무엇을 할 수 있는지 설명해 주시겠습니까? 사전에

감사합니다, 팀

+0

더 느리게 수행되는 쿼리는 더 많은 데이터를 반환하는 쿼리 인 경향이 있습니까? –

+0

안녕하세요. 귀하의 의견에 감사드립니다. 내가 쿼리 문을 제한하기 때문에 쿼리는 모두 최대 56 행을 반환합니다. 그러나 일반적으로 EXPLAIN의 맨 위 행에있는 행이 많을수록 길어 지지만 항상 그렇지는 않습니다. – Tim

+0

Table1의 IX1에서 f2에 포함 된 문자 수를 늘리면 성능에 어떤 영향이 있습니까? 특히 이것을 늘려서 40 개로 늘리면 전혀 개선되지 않습니까? –

답변

1

나는 몇 가지 생각을이 분야의 전문가는 아니지만 현재 위치 : g.F2 변경 때문에 캐싱의 경우

쿼리 속도가 오래 걸립니다. MySQL은 각 쿼리에 대한 결과를 캐시가 가득 찰 때까지 저장하지만 새 쿼리는 빈 캐시에서 실행되므로 시간이 오래 걸립니다. 이를 기반으로 최적화하면 안됩니다. 나는 g 또는 gp 테이블이 큰 특이성을 가지고 있는지 정보에서 말할 수

where 절에 (gp 것 같아?) (How to measure accurately 참조)하지만, 대신 하위 쿼리를 시도 할 수 있습니다.

프로파일 링에 관해서는, 당신이 (스왑을 사용하면 성능에 대한 재앙이다) 그 explain에서 분명, 또는 explain 여부를이 경우에는 단지 잘못하지 않을 램 할당을 초과하는 등의 물리적 임계 값을 타격하고 가능 (How to force the inner query to execute first 참조).

+0

안녕하세요, 의견을 보내 주셔서 감사합니다. 지금 당신이 제안한 것처럼 조인 대신 IN을 사용하도록 위 쿼리를 변경했습니다. 이제 조회는 다음과 같습니다. SELECT g.F1 FROM (SELECT g.F1 FROM DB1.Table1 g WHERE (g.f2 = 'abc')) AS A WHERE A.F1 IN (DB2에서 gp.F1을 선택하십시오. 표 2 gp WHERE (gp.f2 = 452677825)) LIMIT 0,56 쿼리가 훨씬 빠르게 실행됩니다 (~ 1 초, 최대 2 초). 내 임무는 가능한 한이 시도를 더 줄이는 것입니다! – Tim

0

my.cnf를 조정할 수있는 경우 재생할 속성은 key_buffer_size입니다. MyISAM 인덱스는 .MYI 파일에 저장되고 파일 크기를 합산하면 (예 : ls -lh /var/lib/mysql/dbname/*.MYI) 키 버퍼가 얼마나 커야하는지 대략적으로 추정 할 수 있습니다 귀하의 모든 색인에 인치 MySQL의 문서는 시스템 메모리의 25 %를 초과하지 않는 것이 좋습니다 않습니다.

0

두 테이블 간의 관계는 Table1.F1의 경우 대략 다음과 같습니다. 명확히 Table2.F1

100 행 Table1.F1Table2.F1와 일대일 또는 일대의 관계는? 나에게이 문은 일대 다를 의미하지만 스키마에서 각 필드는 기본 (즉, 고유 한) 키입니다.

어쨌든 g.f2(15)의 유니폼이 균일하지 않으며 통계 이상 치가 발생하면 그에 따라 성능이 저하 될 것으로 생각됩니다.

SELECT f2(15) AS f2_15, COUNT(*) AS cnt 
FROM Table1 
GROUP BY f2(15) 
ORDER BY cnt DESC 

의 결과는 몇 가지 중요한 이상 값을 표시합니까?

관련 문제