2012-10-26 2 views
2

나는이 쿼리의 속도를 높이는 데 도움을 받았으며이 테이블의 인덱스 중 일부가 제대로 설정되지 않았다고 생각한다. 나는 또한 그들이 모두 색인이있는 col에 함수가 적용된 b/c로 사용되지는 않을 것이라고 생각한다. 누구든지 내가 어떻게 이러한 테이블이나 쿼리를 최적화 할 수 볼 수 있습니까? requests 테이블은 3 개의 테이블 중 가장 큰 테이블이며 200k 개 이상의 레코드를 포함합니다. devices은 현재 ~ 500 개의 레코드에 저장되어 있으며 clients은 작아집니다.mysql 쿼리 최적화

검색어 :

explain extended SELECT MAX(Request.datetime) AS datetime, Device.id, 
     Device.client_id, Device.mac_address, Device.type, Device.manufacturer, 
     Device.model_number, Client.id, Client.email_address, 
     Request.device_id, Request.datetime, Request.ip_address 
    FROM livefi.devices AS Device 
    LEFT JOIN livefi.clients AS Client 
    ON (Client.id   = Device.client_id) 
INNER JOIN livefi.requests AS Request 
    ON (Request.device_id = Device.id) 
GROUP BY Request.device_id, Request.client_id 

+----+-------------+---------+--------+---------------------------------------------------------+---------------+---------+-------------------------+------+----------+---------------------------------+ 
| id | select_type | table | type | possible_keys           | key   | key_len | ref      | rows | filtered | Extra       | 
+----+-------------+---------+--------+---------------------------------------------------------+---------------+---------+-------------------------+------+----------+---------------------------------+ 
| 1 | SIMPLE  | Device | ALL | PRIMARY             | NULL   | NULL | NULL     | 617 | 100.00 | Using temporary; Using filesort | 
| 1 | SIMPLE  | Client | eq_ref | PRIMARY             | PRIMARY  | 4  | livefi.Device.client_id | 1 | 100.00 |         | 
| 1 | SIMPLE  | Request | ref | idx_device_id,inx_requests_deviceId_datetime_ip_address | idx_device_id | 5  | livefi.Device.id  | 144 | 100.00 | Using where      | 
+----+-------------+---------+--------+---------------------------------------------------------+---------------+---------+-------------------------+------+----------+---------------------------------+ 
3 rows in set, 1 warning (0.04 sec) 

테이블 :

CREATE TABLE `clients` (
    `id` int(10) unsigned NOT NULL AUTO_INCREMENT, 
    `email_address` varchar(100) DEFAULT NULL, 
    `mac_address` varchar(17) DEFAULT NULL, 
    PRIMARY KEY (`id`), 
    UNIQUE KEY `email_address` (`email_address`), 
    KEY `idx_mac_address` (`mac_address`) 
) ENGINE=InnoDB DEFAULT CHARSET=utf8 


CREATE TABLE `devices` (
    `id` int(10) unsigned NOT NULL AUTO_INCREMENT, 
    `client_id` int(10) unsigned DEFAULT NULL, 
    `mac_address` varchar(17) DEFAULT NULL, 
    `type` varchar(25) DEFAULT NULL, 
    `manufacturer` varchar(100) DEFAULT NULL, 
    `model_number` varchar(50) DEFAULT NULL, 
    PRIMARY KEY (`id`), 
    UNIQUE KEY `mac_address` (`mac_address`), 
    KEY `idx_mac_address` (`mac_address`), 
    KEY `fk_devices_clients1` (`client_id`), 
    CONSTRAINT `fk_devices_clients1` FOREIGN KEY (`client_id`) REFERENCES `clients` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION 
) ENGINE=InnoDB AUTO_INCREMENT=492 DEFAULT CHARSET=utf8 


CREATE TABLE `requests` (
    `id` int(10) unsigned NOT NULL AUTO_INCREMENT, 
    `client_id` int(10) unsigned DEFAULT NULL, 
    `device_id` int(10) unsigned DEFAULT NULL, 
    `domain_id` int(10) unsigned DEFAULT NULL, 
    `ip_address` varchar(15) DEFAULT NULL, 
    `datetime` datetime DEFAULT NULL, 
    `gmt_offset` time DEFAULT NULL, 
    `request_method` varchar(15) DEFAULT NULL, 
    `url` text, 
    `http_protocol` varchar(20) DEFAULT NULL, 
    `http_status_code` varchar(20) DEFAULT NULL, 
    `request_size` int(10) unsigned DEFAULT '0', 
    `referer` text, 
    `user_agent` text, 
    `squid_cache_response` varchar(255) DEFAULT NULL, 
    PRIMARY KEY (`id`), 
    KEY `idx_client_id` (`client_id`), 
    KEY `idx_datetime` (`datetime`), 
    KEY `idx_device_id` (`device_id`), 
    KEY `idx_domain_id` (`domain_id`), 
    KEY `idx_id` (`id`), 
    KEY `idx_request_size` (`request_size`), 
    KEY `inx_requests_deviceId_datetime_ip_address` (`device_id`,`datetime`,`ip_address`), 
    CONSTRAINT `fk_requests_clients` FOREIGN KEY (`client_id`) REFERENCES `clients` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION, 
    CONSTRAINT `fk_requests_devices1` FOREIGN KEY (`device_id`) REFERENCES `devices` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION, 
    CONSTRAINT `fk_requests_domains1` FOREIGN KEY (`domain_id`) REFERENCES `domains` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION 
) ENGINE=InnoDB AUTO_INCREMENT=200523 DEFAULT CHARSET=utf8 

답변

0

내가 제안 :

또한
ALTER TABLE requests ADD INDEX (device_id, client_id, datetime); 

때문에, 당신은 당신의 SELECT 절에 Request.datetimeRequest.ip_address을 포함하지 않아야 유의하시기 바랍니다 그들은의 일부가 아닙니다.3210 절. requests의 여러 행에 동일한 device_idclient_id이있을 수 있으며 datetime 또는 ip_address에 대해 선택되는 값이 다소 임의적이기 때문입니다.

0

나는 Device (Device_ID, ID)에 대한 색인을 가지고 있으며, 과거에이를 제공했으며 다른 사람에게 좋았습니다. 날짜는 쿼리에서 병목 현상이 될 수 있지만 정수는 쉽습니다.

장치 AND MAX (ID)의 사전 쿼리를 수행하는 경우 본질적으로 최신 날짜/시간을 반환합니다 ... ID가 자동으로 증가하므로 해당 날짜/시간 값은 다음과 같이 직접 관련됩니다 가장 최근의 .. 그래서 그들은 동일합니다.

거짓 입력을 유발할 수있는 자신 만의 auto-inc ID 열을 추가 할 가능성이있는 일종의 멀티플렉터 서버 클러스터 환경에있는 경우는 예외입니다. 이 경우 색인을 (Device_ID, DateTime)으로 변경하십시오. 말했다

, 나는 다음

SELECT STRAIGHT_JOIN 
     PerQuery.Device_ID, 
     PreQuery.LastRequestID as Request_ID, 
     RDtl.datetime, 
     d.client_id, 
     d.mac_address, 
     d.type, 
     d.manufacturer, 
     d.model_number, 
     c.id, 
     c.email_address, 
     r.ip_address 
    FROM 
     (select rq.Device_ID, 
       MAX(rq.ID) as LastRequestID 
      from 
       livefi.Requests rq 
      group by 
       rq.Device_ID) PreQuery 
     JOIN livefi.Request RDtl 
      ON PreQuery.LastRequestID = RDtl.ID 
      JOIN livefi.Clients c 
       ON RDtl.ClientID = c.ID 
     JOIN livefi.Devices d 
       ON PreQuery.Device_ID = d.ID 

prequery을 할 것이라고는에 의해 그룹과 유일 인덱스에 직접 최적화 할 것 ... 각 장치는 하나 개의 레코드를 반환하고 것이기 때문에 해당 "요청"ID는 "기타"세부 정보, 클라이언트 및 장치 세부 정보에 대한 원래 요청 테이블에 조인합니다.