1

次の構造のテーブルがあります

SHOW CREATE TABLE data_temperature;

CREATE TABLE `data_temperature` (
  `temperature_id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
  `created` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  `data_id` bigint(20) unsigned NOT NULL,
  `x_id` varchar(32) DEFAULT NULL,
  `x_sn` varchar(16) DEFAULT NULL,
  `x_unit` char(1) DEFAULT NULL,
  `x_value` decimal(6,2) DEFAULT NULL,
  PRIMARY KEY (`temperature_id`),
  KEY `created` (`created`),
  KEY `data_id` (`data_id`),
  KEY `x_value` (`x_value`)
) ENGINE=InnoDB AUTO_INCREMENT=6274618 DEFAULT CHARSET=latin1

ここからデータを取得する基本的なクエリがありますが、これは非常に遅いです。そのため、クエリをより単純な用語に分解したところ、この非常に単純なクエリは遅い (17.52 秒) ことがわかりました。

SELECT data_temperature.x_value FROM data_temperature WHERE data_temperature.created BETWEEN '2015-02-02 18:28:42' AND '2015-03-04 18:28:42';

テーブルには 6,274,617 行あります。実際、SELECT COUNT(*) FROM data_temperature3.66 秒もかかります。

このクエリが実行されているシステムは私の開発システムで、Ubuntu 14.04 を実行するクアッドコア、4 GB の RAM、およびソリッドステート ドライブです。

これは、このようなクエリを実行するのにかかる時間についてですか、それとも何か間違っていますか? データを返すより効率的な方法はありますか?

4

1 に答える 1

1

出力の行数を考えてみてください。これらの行がどれだけのディスク容量を占めていたかを考えてみてください。ディスクの動作が遅いことを考えてみてください。これらすべての行をどうするかを考えてください。17秒が妥当です。

同様に、これらの要因のほとんどにより、COUNT(*) は 3.66 秒かかりました。

さらに掘り下げてみましょう。

SELECT COUNT(*) FROM tblInnoDB テーブルでは、インデックスの 1 つを完全にスキャンし、行をカウントします。インデックスは約 100MB になる場合があります。おそらくすべてが既にキャッシュされていることを除いて、ディスクから100MBすべてを取得する必要がありました。そして、6M 行のそれぞれを調べて、数えながら調べなければなりませんでした。合計: 3.66 秒。

次に、他のクエリを見てみましょう。より複雑なため、遅くなります。

その WHERE 句に適切なインデックスがあります: INDEX(created)。それはBTreeにあります。最初に、「2015-02-02 18:28:42」以降の最初のエントリが検索されます。次に、「2015-03-04 18:28:42」になるまで線形に順方向にスキャンします。これにはおそらく 3.66 秒もかかりません。しかし...

インデックス内の各項目について、value. temperature_idこれは、同じ BTree のすぐ隣にあるPRIMARY KEY を最初に見つけることによって取得されcreatedます。を使用してtemperature_id、別の BTree、つまり PK とデータを含む BTree をトラバースして、対応する行を見つけます。そこに が見つかりvalueます。これは非常に範囲内で繰り返されcreatedます。これらのルックアップに必要なブロックは、さらに多くの MB のデータになります。

その SELECT の実行を高速化することは可能ですが、この 1 つのクエリのみに役立ちます: INDEX(created, value). これは「カバー」インデックスです。これは、SELECT に必要なすべての列がインデックス内にあることを意味します。したがって、他の BTree に到達する必要はありません。これにより、時間はおそらく 3.66 秒以下になります。

于 2015-03-05T06:15:03.737 に答える