2017-04-07 2 views
0

테이블 user_notification이 있습니다.SQL 쿼리를 최적화하는 방법

SELECT * FROM `user_notification` `t` WHERE `t`.`status`=2; 

을 실행하는 cron 명령 실행이 어디 상태 일 - Send_fail, 2 대기열 (.이 같은) 3- 성공 주위 ~ 100K 기록 거기 테이블에서

하루 기하 급수적으로하는 증가하고 있습니다 하루. 이 쿼리는 너무 많은 시간이 걸립니다. 이 쿼리를 최적화하는 방법이 있습니까?

#Table structure for table `user_notification` 

CREATE TABLE `user_notification` (
    `id` int(11) NOT NULL, 
    `user_id` int(11) NOT NULL, 
    `notification_id` int(11) NOT NULL, 
    `notification_title` varchar(256) NOT NULL, 
    `notification_message` text NOT NULL, 
    `status` int(1) NOT NULL, 
    `created` int(11) NOT NULL, 
    `updated` int(11) NOT NULL 
) ENGINE=InnoDB DEFAULT CHARSET=latin1; 

ALTER TABLE `user_notification` 
    ADD PRIMARY KEY (`id`), 
    ADD KEY `user_id` (`user_id`), 
    ADD KEY `notification_id` (`notification_id`); 
ALTER TABLE `user_notification` 
    MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=94322; 
ALTER TABLE `user_notification` 
    ADD CONSTRAINT `user_notification_ibfk_1` FOREIGN KEY (`user_id`) REFERENCES `user` (`id`), 
    ADD CONSTRAINT `user_notification_ibfk_2` FOREIGN KEY (`notification_id`) REFERENCES `notification` (`id`); 


# Query_time: 0.010663 Lock_time: 0.000045 Rows_sent: 0 Rows_examined: 17294 
SET timestamp=1491527264; 
SELECT * FROM `user_notification` `t` WHERE `t`.`status`=2; 
+1

쿼리는 실행하는데 0.01 초가 걸린다. 그건 나쁘지 않지만 열 상태에서도 색인을 만들 수 있습니다. –

+0

@Manish 왜 당신의 쿼리에서't'를 사용하고 있습니까? SELECT * FROM user_notification t WHERE t.status = 2;'별칭을 사용할 필요가 없다고 생각합니다. – user3441151

+2

@ user3441151. . . 별칭은 일반적으로 좋은 아이디어이며 낙담해서는 안됩니다. –

답변

0

쿼리가 단지 0.01 초 만에 실행됩니다. 이것은 매우 빠릅니다. 어쨌든 최적화하고 싶다면 할 수있는 일이 몇 가지 있습니다. 우선, 매번 8 개의 열이 모두 필요합니까? 대신

SELECT * 
FROM user_notification t 
WHERE t.status=2; 

을 사용하는 당신은 항상 당신이 실제로 필요한 필드 만 나열해야합니다 :보다

SELECT user_id, notification_id, notification_title, notification_message, status /*change columns as needed*/ 
FROM user_notification t 
WHERE t.status=2; 

기타, 당신은 쿼리 필터링 속도를 열 상태에 대한 인덱스를 만들 수 있습니다.

ALTER TABLE user_notification 
CREATE NONCLUSTERED INDEX i1 ON user_notification (status); 
0

색인 번호 status에 색인을 생성하면 문제를 해결할 수 있습니다.

1

다른 언급했듯이 status 열에 색인을 작성하면 도움이됩니다.

점점 커지고있는 테이블에서 상대적으로 작은 행의 하위 집합 (대기열에있는 행)으로 자주 작업하는 것처럼 들립니다. 자신의 테이블에 "대기중인"레코드를 넣은 다음 상태가 "성공"또는 "실패"로 변경되면 이력 테이블로 이동하는 것이 좋습니다. 그렇게하면 비교적 작은 테이블에서만 쿼리를 수행 할 수 있습니다. 물론이 전략에는 추가 삭제 및 삽입이 포함되므로 응용 프로그램의 작동 방식에 따라 다른 문제가 발생할 수 있습니다.

0

"대기열에 넣지 마십시오. 그냥하십시오."

MySQL이 좋은 대기열 시스템을 만드는 것은 흔한 실수입니다.

항목을 대기열에 넣고 대기열에서 빼는 작업이 간단하게 작업을 수행하려는 노력과 비슷하다면 그렇게하십시오.

좋아, 좋아, 대기열을 가지고 있다고 주장합니까? 그런 다음 Jerrad가 제안한대로 수행하십시오. 아니면 "끝내기 위해 기다리는"일을 가진 여분의 테이블을 가지고있을 수도 있습니다.

폴링을 수행 할 때 트랜잭션 문제가 발생하면주의해야합니다. 그렇지 않으면 두 스레드가 동일한 항목을 가져와 작업 할 수 있습니다.

왜 느린 로그에 0.01s 쿼리가 표시 되었습니까? 아마도 log_queries_not_using_indexes을 켰을 것입니다. (나는 그 설정이 사실상 쓸데없는 것으로 느껴진다. 느린 로그에 혼란 스러울 뿐이다.)

관련 문제