2016-05-26 1 views
0

同じエントリの他のデータ(IDと他のプロパティ)を保持しながら、古いデータベースエントリのペイロードを削除する必要があります。 テーブルにはメッセージIDカラム(他の情報と連結された日付スタンプで構成されています)、コンテンツカラム(これはBLOBで、データベースの合計サイズの90%以上になります)この場合のために。 - 私はコンテンツを交換 大きなMySQLデータベースの古いエントリを単一の列からパージする方法はありますか?

UPDATE LOW_PRIORITY repository SET content="" WHERE SUBSTR(message_id, 6, 6)<201601 AND message_box = "IN"; 

は、私はすべてのエントリーMESSAGE_IDから YYYYMMを抽出し、それが選ばれたカットオフの月よりも古いかどう:

は、私が最初の条件で簡単な更新を実行しようとしました空の文字列。

データベースのサイズは25ギガバイトを超えている、と私のテーブルにはほとんど2KKエントリを保持しており、非常に控えめなハードウェア上で実行されている、と私のクエリは、いくつかの時間のために実行した後にエラーで失敗しました:通常

ERROR 2013 (HY000): Lost connection to MySQL server during query 

私は

set global max_allowed_packet=104857600; 

は私のUPDATEクエリを再実行している:ので、私は行って、100MBのパケットサイズ処理するための設定を更新し、データベース変数を変更することを避けるためにしようと、私はあなたが大規模なダンプファイルからデータベースを復元しようとすると、このエラーはまた、ポップアップ表示を知っていました新しいエラーが発生しました:私のMySQLサーバは非常に控えめなハードウェア上で実行され、私は、サーバーが利用可能なリソースを超えて作ることができ、設定を変更したくないので代わりに利用可能なすべてのタイムアウトデータベースを増やしたい - 私は前に述べたように

ERROR 2013 (HY000): Lost connection to MySQL server during query 

変数は、私はこのようなクエリで小さなチャンクでの私のクエリを実行することを決定しました:

ERROR 1206 (HY000): The total number of locks exceeds the lock table size 
:このクエリはエラーで失敗し

UPDATE LOW_PRIORITY repository SET content="" WHERE message_id in (select message_id from(select message_id from repository where SUBSTR(message_id, 6, 6)<201603 AND message_box = "IN" limit 0, 1000)as temp); 

"limit 1"で1行に制限されている場合でも同じクエリで失敗します!

ページネーションを間違って使用していますか、これを行うには別の方法がありますか?

* DBは、1GBのRAMと100GBのHDDを備えたデュアルコアIntel CPUを搭載した仮想Ubuntuサーバを実行しています。私はそれが日々の仕事には十分ではありません。この1つのクエリだけで仕様を増やしたくないのが本当です。

答えて

1

複雑な方法(複雑な=より多くのリソース)で、望ましくないこと(をin-文で使用)をするようにmysqlを騙そうとしています。それは間違っていないですが、ちょうどこれはまだそれのコンテンツを持っている最初の1000の古い行を更新します

UPDATE LOW_PRIORITY repository SET content="" 
WHERE content <> "" 
and SUBSTR(message_id, 6, 6) < 201603 AND message_box = "IN" 
limit 1000; 

を書くことができます。

+0

完璧な解決策! 私は実際にする必要がなかったときに改ページしようとしていました。影響を受ける行の数を制限しようとすると、手作業で範囲を選択しようとしましたが、サブクエリなしでは_UPDATE_では不可能です。代わりに、すでに更新された行を除外する別の条件を追加し、クエリが再度ヒットするかどうか気にする必要はありません。 – Andris

0

ここで問題となるのは、WHERE条件がmessage_idフィールドのインデックスを使用できないということです。

なぜ単にない:

WHERE message_id < 20160100* ... 

が、これはあなたの結果には変化はないだろうので、**はとにかく201601 **少なくなり、整数フィールド、201512であると仮定。しかし、部分文字列関数を削除すると、そのフィールドにインデックスを使用できるようになります。

+0

残念ながら、それは文字列です。いくつかの英数字の値が連結されています。さらに、異なる_messagebox_値は、_message_id_の内部の異なる位置に日付スタンプを持つでしょう。 – Andris

関連する問題