2

次の表を使用してMySQL/ISAMデータベースを実行しています。

create table measurements (
  `tm_stamp` int(11) NOT NULL DEFAULT '0',
  `fk_channel` int(11) NOT NULL DEFAULT '0',
  `value` int(11) DEFAULT NULL,
  PRIMARY KEY (`tm_stamp`,`fk_channel`)
);

tm_stamp-のfk_channel組み合わせは一意である必要があるため、複合主キーです。現在、特定の無関係な理由により、データベースはInnoDBエンジンに移行されます。それについて何かをグーグルで調べたところ、キーがディスク上のデータの物理的な順序を決定することがわかりました。現在、クエリの90%は次のようになっています。

SELECT value FROM measurements
WHERE fk_channel=A AND tm_stamp>=B and tm_stamp<=C
ORDER BY tm_stamp ASC

インサートは99%の順でtm_stamp、データロガーネットワーク用のストレージです。テーブルの行数は少ないですが、着実に増加しています。質問は

  1. ストレージエンジンを変更するだけで、パフォーマンスが大幅に変化するのでしょうか。
  2. 最も人気のあるSELECTに関して、インデックスの列の順序は重要ですか?このブログはその線に沿って何かを提案します。
  3. クラスタ化インデックスの性質のおかげで、おそらくORDER BY句を省略して、パフォーマンスを向上させることができるでしょうか。
4

3 に答える 3

1

編集1

主キーをから変更するようです

PRIMARY KEY (`tm_stamp`,`fk_channel`)

PRIMARY KEY (`fk_channel`,`tm_stamp`)

MyISAMとInnoDBの両方にとって、常に意味があります。これが正しいことの証明については、 http://sqlfiddle.com/#!2/0aa08/1を参照してください。

元の答え:

変更するかどうかを判断するには

PRIMARY KEY (`tm_stamp`,`fk_channel`)

PRIMARY KEY (`fk_channel`,`tm_stamp`)

クエリのパフォーマンスを向上させるには、どのフィールドの値のカーディナリティが高いか(どのフィールドの値がより多様であるか)を判断する必要があります。ランニング

SELECT COUNT(DISTINCT tm_stamp), COUNT(DISTINCT fk_channel) FROM measurements;

列のカーディナリティが得られます。

それで、あなたの質問に正しく答えるために、私たちは最初に知る必要があります:との間の値の一般的な範囲は何BですかC?60?3,600?86,400?もっと?

たとえば、

SELECT COUNT(DISTINCT tm_stamp), COUNT(DISTINCT fk_channel) FROM measurements;

32,768と256を返します。32,768を256で割ると128になります。これはtm_stamp、の値ごとに128の一意の値があることを示していますfk_channel

Bしたがって、との差Cが通常128未満の場合tm_stampは、主キーの最初のフィールドとして残します。128以上の場合はfk_channel、最初のフィールドを作成します。

別の質問:(40億の一意の値、その半分は負の値)であるfk_channel必要がありますか?INTそうでない場合は、(256個の一意の値がある場合)または(65536個の一意の値)に変更fk_channelすると、時間とスペースを大幅に節約できます。TINYINT UNSIGNEDSMALLINT UNSIGNED

たとえば、256の可能な最大fk_channel値と65,536の可能な値があるとするとvalue、次の方法でスキーマを変更できます。

create table measurements_new (
  tm_stamp INT UNSIGNED NOT NULL DEFAULT '0',
  fk_channel TINYINT UNSIGNED NOT NULL DEFAULT '0', -- remove UNSIGNED if values can be negative
  value SMALLINT UNSIGNED DEFAULT NULL, -- remove UNSIGNED if values can be negative
  PRIMARY KEY (tm_stamp,fk_channel)
) ENGINE=InnoDB
SELECT
  tm_stamp,
  fk_channel,
  value
FROM
  measurements
ORDER BY
  tm_stamp,
  fk_channel;

RENAME TABLE measurements TO measurements_old, measurements_new TO measurements;

これにより、既存のデータが新しいテーブルにPRIMARY KEY順番に格納され、パフォーマンスがいくらか向上します。

于 2012-10-24T23:17:28.230 に答える
1

クエリを見つめる

SELECT value FROM measurements
WHERE fk_channel=A AND tm_stamp>=B and tm_stamp<=C
ORDER BY tm_stamp ASC

静的な値はfk_channelであり、移動する順序付きの値はtm_stampです。これは、クエリのニーズの中心にあると思われる2番目の質問に対処します。

PRIMARY KEY列を逆にした方がはるかに良いでしょう

create table measurements (
  `tm_stamp` int(11) NOT NULL DEFAULT '0',
  `fk_channel` int(11) NOT NULL DEFAULT '0',
  `value` int(11) DEFAULT NULL,
  PRIMARY KEY (`fk_channel`,`tm_stamp`)
);

最初の質問に関しては、ストレージエンジンが何をキャッシュするかを決定します。

MyISAMを使用している場合は、主キーを変更してvalue列を含めることができます。

create table measurements (
  `tm_stamp` int(11) NOT NULL DEFAULT '0',
  `fk_channel` int(11) NOT NULL DEFAULT '0',
  `value` int(11) DEFAULT NULL,
  PRIMARY KEY (`fk_channel`,`tm_stamp`,`value`)
) ENGINE=MyISAM;

このように、クエリのデータ取得は、厳密には最大で1つのファイル(MyISAMテーブルの.MYI)から行われます。テーブルを読み取る必要はまったくありません。

InnoDBへのスイッチがfk_channelRAMtm_stampに2回ロードされる場合

  • InnoDBデータページから1回
  • InnoDBインデックスページから1回
于 2012-10-24T20:36:32.083 に答える
0

句内の引数の順序はWHEREここでは不規則です。オプティマイザは最適なキーオプションを選択します(通常、>または<比較でのインデックス付きフィールドの直接比較)。最初の例では、最良のオプションはtm_stamp<>比較でしたが、これは直接の等価性チェックではなかったため、標準以下でした。

ただし、クラスター化されたキーの順序は重要です。正確な比較が常にfk_channel列にある場合は、PKを次のように変更します。

   PRIMARY KEY (`fk_channel`,`tm_stamp`)

fk_channel=Aこれで、where句の恩恵を受けるインデックスができました。

また、ストレージエンジンはある程度の役割を果たしますが、ここでの問題はinnodbとmyisamの間にあるとは思いません。

ORDER BY最後に、この条項はあなたの問題にはあまり関係がないと思います。それはクエリ後に行われます。グループ化すると、パフォーマンスに影響を与える可能性があります。

于 2012-10-24T20:29:19.857 に答える