web-dev-qa-db-ja.com

テーブルがいっぱいです-MariaDB

実行時間の長いクエリを実行しようとすると、次のエラーが発生します。

テーブル「C:\ Windows\SERVIC〜2\NETWOR〜1\AppData\Local\Temp#sql1664_349_19be」がいっぱいです

サーバーのCドライブ(NTFS)には135GBの空き容量があります。データを保持するDドライブ(NTFS)には、800 GBのうち365 GBの空き容量があります。

サーバーには32GB RAMがあります。

私が実行しているクエリはかなり単純ですが、6100万行に対して実行されます。

Tblinvoiceに18のインデックスがあり、テーブルはINNODBです。

SELECT
    InvoiceNo,
    NetAmountAbs,
    InvoiceDate
  FROM tblinvoice
  WHERE GrossAmountAbs >= 200
  GROUP BY InvoiceNo,
           NetAmountAbs,
           InvoiceDate
  HAVING COUNT(*) > 1
  AND SUM(CASE WHEN NetAmount_Doc >= 0 THEN 1 ELSE 0 END) > 1
  AND MIN(AccountNumber) != MAX(AccountNumber)
  AND MAX(GrossAmountAbs) != MIN(GrossAmountAbs)
  AND MAX(ImportID) = 2

これはmy.iniファイルです

[mysqld] 
log_bin_trust_function_creators=1 
datadir=E:/MariaDB 10.2.8
port=3306 
sql_mode="STRICT_TRANS_TABLES,NO_ENGINE_SUBSTITUTION"
default_storage_engine=innodb 
innodb_buffer_pool_size=25000M
character-set-server=utf8 
innodb_io_capacity=200
innodb_read_io_threads=64 
innodb_thread_concurrency=0
innodb_write_io_threads=64 
max_connections=1000
innodb_lock_wait_timeout=50 
lower_case_table_names=2
event_scheduler=on 
character-set-server=utf8 
max_allowed_packet=100M
connect_timeout=10 
innodb-log-file-size=1G
innodb_log_buffer_size=64M
tmp_table_size=2G
max_heap_table_size=2G 
[client] 
port=3306 
plugin-dir=C:/ProgramFiles/MariaDB 10.2/lib/plugin

ありがとう

編集: my.iniを更新し、innodb-log-file-size、innodb_log_buffer_size、tmp_table_size、max_heap_table_size、

2
SkelDave

エラーメッセージに騙されないでください。

エラーはtable is fullであることに注意してください。 disk is fullは表示されません。

table is full条件を作成するものは何ですか?

これは、トランザクションのロールバックセグメントに注がれている変更に関係しています。

私は何度もこれに対処しました

次のいずれかが発生したようです

  • SELECTはトランザクションの最中でした
  • SELECTは、多くのトランザクションに直面してロールバック情報を保持しすぎました

どちらの場合でも、tblinvoiceテーブルには保留中の変更が多すぎるため、SELECTはあきらめる必要がありました。これにより、tblinvoiceに対するすべての書き込みトランザクションがロールバックされた可能性があります。

このSELECTを、tblinvoiceに対する書き込みが多い多忙なマスターで実行している場合、このSELECTでこの問題が発生する可能性があります。

レポートスレーブ(MySQLレプリケーションを実行)をセットアップし、メインサーバーではなくこのタイプのクエリを実行する必要があります。

UPDATE 2018-02-27 10:10 EDT

あなたの問題はRAM無料の量かもしれません。

あなたは現在これを持っています

tmp_table_size=2G
max_heap_table_size=2G

一時テーブルがすぐにディスクに移動するように、クエリを再実行してください

set tmp_table_size = 1024 * 1024 * 16;
set max_heap_table_size = 1024 * 1024 * 16;
SELECT
    InvoiceNo,
    NetAmountAbs,
    InvoiceDate
  FROM tblinvoice
  WHERE GrossAmountAbs >= 200
  GROUP BY InvoiceNo,
           NetAmountAbs,
           InvoiceDate
  HAVING COUNT(*) > 1
  AND SUM(CASE WHEN NetAmount_Doc >= 0 THEN 1 ELSE 0 END) > 1
  AND MIN(AccountNumber) != MAX(AccountNumber)
  AND MAX(GrossAmountAbs) != MIN(GrossAmountAbs)
  AND MAX(ImportID) = 2;

C:\Windows\SERVIC~2\NETWOR~1\AppData\Localフォルダを監視してください。そのフォルダーに表示される一時ファイルを確認します。私が望んでいるのは、一時テーブルがディスク上の必要なサイズに達することです。どうして ?

tmp_table_size=2Gおよびmax_heap_table_size=2Gを使用すると、一時テーブルは、ディスクに転送する前に、RAMで2Gに到達する必要があります。私の作業理論では、2 GBのRAM=無料(Windowsの話をしていますよね???)とにかくデフォルト値です)試してみてください!!!

2
RolandoMySQLDBA
tmp_table_size=2G
max_heap_table_size=2G 

それらは危険なほど大きいです。 RAM-約300Mの約1%を超えないようにしてください。これらの設定は、複雑なSELECTs内のtmpテーブルで使用されます。クエリはそのようなものです。複数の複雑なクエリの場合複数の[〜#〜] ram [〜#〜] 2GBの割り当てが同時に発生し、それによってRAMが破壊されている可能性があります。

Temp#sql1664_349_19beは、このようなtmpテーブル名のように見えます。

ibdata1は任意に大きくすることができます-ディスク容量によってのみ制限されます(そしてテラバイト単位の非常に大きなハード制限、またはOS制限)。 autoextendはありましたかibdata134025472Kは32Gを超えるため、OSの制限とは見なされません。

SHOW CREATE TABLE

提供してください EXPLAIN SELECT ...

2
Rick James

大量のRAM=をMySQLパラメータに配置することは考えていません。

sort_buffer_size=
join_buffer_size=
read_buffer_size=
read_rnd_buffer_size
tmp_table_size
max_heap_table_size

、は良いアイデアです。私が知っているのは、RAM=の大きなサイズを予約するのは遅いプロセスであるため、大量の値によってMySQLの速度が低下するためです。これは以前のテストで見つけたものなので、システムに十分なRAMが搭載されている場合でも、RAM)を同様のパラメータに大量に配置することはお勧めしません。

0
linuxman1