2

このクエリを高速化するように依頼されましたが、これらのテーブルの一部のインデックスが正しく設定されていないと思います。また、すべてが使用されるわけではないと思います。b/ ca関数は、インデックスを作成している列に適用されます。これらのテーブルやクエリを最適化する方法を誰かが理解できますか?このrequestsテーブルは3つの中で最大のテーブルになり、200k以上のレコードが含まれます。devices現在、最大500のレコードclientsがあり、さらに小さくなります。

クエリ:

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
4

2 に答える 2

0

私は ( Device_ID, ID ) 上のデバイスのインデックスを持っていて、過去にこれを提供したことがありますが、他の人にとってはうまく機能しているようです。日付はクエリのボトルネックになる可能性がありますが、整数は簡単です。

Device 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

プレクエリはグループ化された唯一のものであり、インデックスに直接最適化されます...各デバイスは1つのレコードとそれに対応する「リクエスト」IDのみを返すため、「その他」の元のリクエストテーブルに結合されます"詳細、クライアントとデバイスの詳細。

于 2012-11-01T23:20:31.340 に答える
0

私は提案します:

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

また、 nor は節の一部ではないため、節に含めRequest.datetimeないRequest.ip_addressでください。これは、 のいくつかの行に同じとが含まれている可能性があり、どの値が選択されるか、または多少ランダムであるためです。SELECTGROUP BYrequestsdevice_idclient_iddatetimeip_address

于 2012-11-01T21:54:18.763 に答える