2012-12-20 2 views
2

인덱스 (또는 실제로 쿼리 자체)를 사용하여 MySQL 쿼리를 최적화하는 방법에 대한 도움이 필요하십니까?쿼리 최적화

테이블 구조 :

CREATE TABLE IF NOT EXISTS `match_current` (
    `partnership_id` int(11) NOT NULL AUTO_INCREMENT, 
    `runs` int(5) NOT NULL DEFAULT '0', 
    `balls` int(5) NOT NULL DEFAULT '0', 
    `user1_id` bigint(11) NOT NULL, 
    `user1_firstname` char(20) NOT NULL, 
    `user1_lastname` char(20) NOT NULL, 
    `user1_runs` int(5) NOT NULL DEFAULT '0', 
    `user1_balls` int(5) NOT NULL DEFAULT '0', 
    `user1_strike` tinyint(1) NOT NULL DEFAULT '1', 
    `user1_out` tinyint(1) NOT NULL DEFAULT '0', 
    `user1_retired` tinyint(1) NOT NULL DEFAULT '0', 
    `user2_id` bigint(11) NOT NULL, 
    `user2_firstname` char(20) NOT NULL, 
    `user2_lastname` char(20) NOT NULL, 
    `user2_runs` int(5) NOT NULL DEFAULT '0', 
    `user2_balls` int(5) NOT NULL DEFAULT '0', 
    `user2_strike` tinyint(1) NOT NULL DEFAULT '0', 
    `user2_out` tinyint(1) NOT NULL DEFAULT '0', 
    `user2_retired` tinyint(1) NOT NULL DEFAULT '0', 
    `last_over` char(15) NOT NULL, 
    `ball_by_ball` varchar(1000) NOT NULL, 
    `facebook` tinyint(1) NOT NULL DEFAULT '0', 
    `friends` tinyint(1) NOT NULL DEFAULT '0', 
    `nudge` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', 
    `started` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', 
    `status` tinyint(1) NOT NULL DEFAULT '1', 
    `timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, 
    PRIMARY KEY (`partnership_id`), 
    UNIQUE KEY `user1_id_2` (`user1_id`,`user2_id`,`facebook`), 
    KEY `user2_id` (`user2_id`), 
    KEY `user1_id` (`user1_id`), 
    KEY `facebook` (`facebook`), 
    KEY `status` (`status`), 
    KEY `friends` (`friends`), 
    KEY `timestamp` (`timestamp`), 
    KEY `user1_id_3` (`user1_id`,`user1_strike`), 
    KEY `user2_id_2` (`user2_id`,`user2_strike`) 
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=36139 ; 

예제 쿼리 :

SELECT * 
FROM match 
WHERE status = 1 
AND (
    (user1_id=1234 AND user1_strike=1) OR 
    (user2_id=4321 AND user2_strike=1) 
) 
ORDER BY timestamp ASC 

쿼리 분명히 작동하고 너무 나쁜 일을하지 않은 그러나 우리는 정말 최근에 트래픽을 증가했습니다 지금은 그것이 시작하고있다 볼 수 있습니다 투쟁하기.

건배!

+4

최적화를 위해 사람들은 테이블 구조/인덱스가 무엇인지 알아야합니다. 당신의 질문에'SHOW CREATE TABLE match'의 출력을 추가하는 것을 고려해보십시오. – Andris

+0

어떤 열을 인덱스로 설정 하시겠습니까? 인덱스는 숫자 또는 날짜 시간 열이 아닌 문자열 mathcing 및 검색을위한 것입니다 ... – shadyyx

+0

보유하고있는 인덱스를 표시해야합니다. – paulgrav

답변

0

정말 필요한 것이 있습니까?

SELECT * 

가, 인덱스를 만들기 절

INDEX(user1_id, user1_strike, user2_id, user2_strike) 

당신은 또한 timestemp을 포함 인덱스에 ASC에 순서를 설정할 수있는 곳.

다음으로 데이터베이스 테이블에 추가 색인이 필요하고 어쩌면 다시 설계해야 할 수도 있습니다. 또한 SQL 서버 설정 (InnoDB 테이블을 사용하고 서버에 대한 올바른 캐시/메모리 제한을 설정)을 확인하십시오.

+1

다음은 생각입니다. 부엌 싱크대에 색인을 붙이자. –

2

쿼리를 최적화하는 동안 염두에 두어야 할 점 중 하나는 쿼리를 수행 할 때 인덱스 만 을 선택한다는 것입니다. 맹목적으로 당신이 생각할 수있는 필드의 조합을 색인 생성하면 많은 도움이되지 않을 수 있으며 실제로 삽입 속도가 느려집니다.

이것은 당신이 조회 된 사용자가 user1에있을 것 또는 user2 당신이 모두를 검색 있는지 확실하지 때문에, 그래서 두 선수가 팀을 형성하는 전형적인 테이블처럼 보인다. 이 경우 모든 키가 거부되고 결과적으로 테이블 스캔이 수행됩니다.

내 조언이 약간 테이블을 비정규하고 스패닝 기본 키와 결합 (user_id, partnership_id)를 저장하는 별도의 테이블을 생성하는 것, partnerships의 각 레코드는이 테이블에 두 개의 레코드입니다; 이렇게하면 OR이 제거되고 단순한 JOIN을 사용하여 더 큰 테이블에서 필요한 정보를 얻을 수 있습니다.

EXPLAIN <query>을 사용하면 이러한 문제를 조사하는 데 도움이되므로 MySQL이 쿼리를 "공격"하는 방식을 확인할 수 있습니다.