2014-07-24 3 views
1

8000 만 개의 행이있는 큰 테이블과 두 개의 다른 테이블을 업데이트하는 트리거가 있습니다. 이들 모두는 TokuDB입니다. 서버는 트리거 코드가MySQL 5.6 트리거의 성능이 느림

if NEW.ip_addr <> "" THEN 
    -- get the current oldest date 
    -- set @maxdate := now(); 
    set @maxdate := (select lastseen from uniq_ip where data = NEW.ip_addr); 
    INSERT INTO uniq_ip (`data`, `total`, `lastseen`) 
    VALUES (NEW.ip_addr, 1, NEW.timestamp, @subnet) 
    ON DUPLICATE KEY UPDATE total = total + 1, lastseen = latest_date(NEW.timestamp, @maxdate); 
end if; 
-- get all values in one go, its indexed some query comes from index. 
if NEW.username <> "" THEN 
      -- get the current oldest date 
      set @maxdate := (select lastseen from uniq_username where data = NEW.username); 

      INSERT INTO uniq_username (`data`, `total`, `lastseen`) 
      VALUES (NEW.username, 1, NEW.timestamp) 
      ON DUPLICATE KEY UPDATE total = total + 1, lastseen = latest_date(NEW.timestamp, @maxdate); 
end if; 

과 uniq_username 및 uniq_ip이있다

CREATE TABLE `main` (
    `id` int(11) NOT NULL AUTO_INCREMENT, 
    `timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, 
    `ip_addr` varchar(50) NOT NULL DEFAULT '', 
    `username` varchar(255) NOT NULL DEFAULT ''. 
    PRIMARY KEY (`id`), 
) ENGINE=TokuDB; 

Percona 5.6을 실행하는

CREATE TABLE `uniq_ip` (
    `data` varchar(42) NOT NULL, 
    `total` mediumint(4) unsigned NOT NULL DEFAULT '0', 
    `lastseen` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', 
    PRIMARY KEY (`data`), 
    KEY `idx_lastseen` (`data`,`lastseen`) 
) ENGINE=TokuDB DEFAULT CHARSET=ascii; 


CREATE TABLE `uniq_username` (
    `data` varchar(255) CHARACTER SET latin1 NOT NULL, 
    `total` mediumint(4) unsigned NOT NULL DEFAULT '0', 
    `lastseen` datetime NOT NULL DEFAULT '0000-00-00 00:00:00', 
    PRIMARY KEY (`data`), 
    KEY `idx_data_time` (`data`,`lastseen`) 
) ENGINE=TokuDB DEFAULT CHARSET=utf8; 

문제는 부하 상태에서 대량 삽입이 완벽하게 작동한다는 것입니다 timeseen 값을 계산할 때 트리거의 username 부분. 당신이 얻을 지금 (로 설정하면이

set @maxdate := (select lastseen from uniq_ip where data = NEW.ip_addr);

를 처리 할 때 그러나 함수의 첫 번째 부분)을 uniq_ip 테이블에서 동일한 30/s의 800/s의에서 삽입 속도를 떨어 그것의 빠른을 할 수 (그러나 정확한 결과는 아닙니다). uniq_username과 uniq_ip는 동일한 구조와 인덱스를 가지며 트리거는 사용자가 먼저 처리하는 (사용자 이름 또는 IP) 관계없이 트리거를 느리게하는 위의 명령문 만 제외하고 오른쪽으로 느려집니다.

아래의 문제는 uniq_ip 테이블이 TokuDB 또는 InnoDB이고 기본 charset이 차이가 없으면 insert 문이 활성화되거나 주석 처리되지 않습니다. Latest_date()는 가장 최근 날짜 시간을 반환하는 작은 함수입니다.

아이디어 또는 팁?

답변

0

main.ip_addr

감사는 라틴과 uniq_ip.data은 UTF으로 캐스팅되었다. uniq_ip.data를 latin1로 변경하면 삽입 빈도가 50 개 삽입/초에서 1000 개 삽입/초로 향상되었습니다. 나는 latin1 -> utf8 캐스팅이 cpu 살인자라고 생각한다.