2

17.6m 行のテーブルがあります

'CREATE TABLE `tmp_hist` (
`ti` int(11) DEFAULT NULL,
`cip6` varchar(15) DEFAULT NULL,
`date` varchar(20) DEFAULT NULL,
`fact` int(11) DEFAULT NULL,
`se` char(1) DEFAULT NULL,
`oper` int(11) DEFAULT NULL,
`qte` int(11) DEFAULT NULL,
`prix` double DEFAULT NULL,
`cip` int(11) DEFAULT NULL,
`fl` int(11) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1'

非常に単純な更新を実行するには、約 10 分かかります。

update tmp_hist set cip=100

時間があります:

  • 39sec -- テーブル tmp_hist を修復します (myisam では、テーブルを修復すると別のファイルにコピーされ、元のファイルが置き換えられるため、これは特に興味深いものです。これはディスク速度を示します)
  • 531sec -- tmp_hist set cip=100 を更新
  • 400sec -- CREATE TABLE tmp_inno SELECT * FROM tmp_hist (ここでは、テーブルを InnoDB に変換しようとしています)
  • 317sec -- tmp_inno set cip=999 を更新します (これは InnoDb にあります)

すべての仮定により、更新時間は修復時間、つまり 40 秒と非常によく似ていると予想されます。でも10分はかかります!それをスピードアップするために何ができますか?問題のコードは、一部のデータを形式 A から形式 B に変換します。同じデータに他のユーザーがアクセスすることなく、単一のスレッドで実行されることが保証されています。

PS: UPDATE ステートメントはテスト用に単純化されています (すべての時間は、この単純化された更新のためのものです)。実際のコードは行ごとに異なる値を設定しますが、実際の更新の実行時間は単純化された更新とほぼ同じであることがわかったので、問題を単純化したものに絞り込みました。

現在の進行

回答の知識を使用して、ROW_FORMAT=FIXED (すべての列タイプを固定に変更するのと同じように見えます) を適用すると、更新時間が 145 秒に短縮され、ほぼ 4 倍高速になりました。

それでも、修理時間の約 2.5 倍遅く、到達可能な時間であると私は考えています。

4

1 に答える 1

4

テーブルにvarchars があるため、更新では行を読み取り、正しいオフセットを探してから cip フィールドを更新する必要があります。さらに、行は可変サイズであるため、エンジンは単一レコードのオフセットを簡単に判断できません。したがって、これが違いを生む場合は、varcharフィールドを固定charおよびテストに変更してみてください。

このトピックもカバーする興味深い回答は、dba SE https://dba.stackexchange.com/a/2643にあります。

于 2012-12-06T11:07:41.290 に答える