1

非常に遅い次の SQL ステートメントがあります。それは600-800msまで変化します!

最適化する方法を探していますが、最適なルートが正確にはわかりません。私のデータベースはかなり大きく、entriesテーブルには 400,000 行、devicesテーブルには 90,000 行あります。


SQL ステートメント

SELECT devices.manufacturer, COUNT(devices.manufacturer) AS device_count 
FROM entries 
   JOIN devices ON entries.device_id=devices.id 
WHERE waypoint_id IN (1,2,3,5) 
  AND entries.updated_at >= '2013-06-20 21:01:40 -0400' 
  AND entries.updated_at <= '2013-06-27 21:01:40 -0400'
  GROUP BY devices.manufacturer;

貧弱なハードウェアで実行しているため、またはステートメントが正しくないため、またはテーブルを正しく構造化していないため、この SQL ステートメントは遅いですか? どんな考えでも大歓迎です!


声明の目的

すべてのデバイス メーカーのリストと、そのメーカーがエントリ テーブルに表示された回数の関連カウントを取得します。


テーブル構造

デバイス

id int(11) NOT NULL AUTO_INCREMENT,
mac_address varchar(255) DEFAULT NULL,
user_id int(11) DEFAULT NULL,
created_at datetime NOT NULL,
updated_at datetime NOT NULL,
manufacturer varchar(255) DEFAULT NULL,
PRIMARY KEY (id),
UNIQUE KEY mac_address (mac_address),
KEY manufacturer (manufacturer)
ENGINE=InnoDB AUTO_INCREMENT=839310 DEFAULT CHARSET=utf8;

エントリー

id int(11) NOT NULL AUTO_INCREMENT,
device_id int(11) DEFAULT NULL,
created_at datetime NOT NULL,
updated_at datetime NOT NULL,
waypoint_id int(11) DEFAULT NULL,
unsure tinyint(1) DEFAULT '0',
PRIMARY KEY (id),
KEY device_index (device_id)
ENGINE=InnoDB AUTO_INCREMENT=3389538 DEFAULT CHARSET=utf8;

また、別のデータベースを調べています。このデータベースが将来的に非常に高速な読み取り/書き込みを必要とすることを考えると、Redis のようなものが役に立ちますか?

4

2 に答える 2

2

に複数列のインデックスを追加すると、クエリの実行速度が向上しますentries(waypoint_id, updated_at)

また、クエリは次のようになります。

SELECT
    devices.manufacturer,
    COUNT(devices.manufacturer) AS device_count 
FROM
    entries
JOIN
    devices ON devices.id = entries.device_id
WHERE
    entries.waypoint_id IN (1,2,3,5)
AND
    entries.updated_at BETWEEN '2013-06-20 21:01:40 -0400' AND '2013-06-27 21:01:40 -0400'
GROUP BY
    devices.device_id

device_idPS:外部キーとして明示的に宣言するのは良いことではないでしょうか?

于 2013-06-28T02:40:57.143 に答える
1

の索引が必要ですEntries {waypoint_id, updated_at}。これは以下を満たす必要があります。

WHERE waypoint_id IN (1,2,3,5) 
  AND entries.updated_at >= '2013-06-20 21:01:40 -0400' 
  AND entries.updated_at <= '2013-06-27 21:01:40 -0400';

実際のカーディナリティに応じて、この複合インデックスのフィールドの順序を逆にしたい場合と逆にしたくない場合があります。

または、 にカバリングインデックスを作成して、テーブル全体Entries {waypoint_id, updated_at, device_id}へのアクセスを回避します。Entries


その上で、 にインデックスを作成することを検討してDevices {id, manufacturer}ください。うまくいけば、My​​SQL は、テーブルにアクセスすることさえせずに JOIN と集計の両方を満たすためにそれを使用するのに十分スマートになりDevicesます。

于 2013-06-28T02:47:24.280 に答える