web-dev-qa-db-ja.com

JSONの「マージ」操作を使用するJSON列を含むMySQL 8.0テーブルには50万行ありますが、分析テーブルには7MMと表示されます

TABLE STATUSによると7MMの行を持つデータベーステーブルがありますが、SELECT COUNT(*)を実行すると500k行しかありません。

テーブルの増加が増加しており、現在ストレージが不足しているため、これは問題です。

これがスキーマです:MySQL 8.0.15

CREATE TABLE `tasks` (
  `task_id` binary(24) NOT NULL,
  `task` json NOT NULL,
  `task_kryo` mediumblob,
  `task_type` varchar(180) COLLATE utf8_bin GENERATED ALWAYS AS (json_unquote(json_extract(`task`,_utf8mb4'$.t'))) STORED,
  `created` datetime GENERATED ALWAYS AS (cast(left(json_unquote(json_extract(`task`,_utf8mb4'$._task.timestamp')),19) as datetime)) STORED,
  `last_updated` datetime GENERATED ALWAYS AS (cast(left(json_unquote(json_extract(`task`,_utf8mb4'$._task.latestStatus.timestamp')),19) as datetime)) STORED,
  `latest_status` varchar(180) COLLATE utf8_bin GENERATED ALWAYS AS (json_unquote(json_extract(`task`,_utf8mb4'$._task.latestStatus.t'))) STORED,
  `marker` binary(24) GENERATED ALWAYS AS (json_unquote(json_extract(`task`,_utf8mb4'$.marker'))) STORED,
  PRIMARY KEY (`task_id`),
  KEY `task_type_index` (`task_type`),
  KEY `created_index` (`created`),
  KEY `last_updated_index` (`last_updated`),
  KEY `latest_status_index` (`latest_status`),
  KEY `marker_index` (`marker`),
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;

これは、AWS上のMySQL RDSです。このテーブルは完全に使い捨てデータであるため、システムバックアップは無効になっています。その結果、このテーブルのバイナリログはありません。 AWSは、システムバックアップを無効にすると明らかに無効になります

私の疑いは、UpdateステートメントでJSON "Merge"操作を使用していることと、バイナリログがAWSによって無効になっているためです(このテーブルは完全に使い捨て/スクラッチデータであるため、このテーブルのバックアップはありません)。テーブルへの挿入(古いレコードは残りますが、削除されません)。

参照 https://mysqlhighavailability.com/efficient-json-replication-in-mysql-8-0/

binlog-row-value-options = PARTIAL_JSON

また、MySQLログには再起動時に次の警告が含まれます。

2020-05-21T20:02:08.506526Z 0 [Warning] [MY-013103] [Server] When binlog_row_image=FULL, the option binlog_row_value_options=PARTIAL_JSON will be used only for the after-image. Full values will be written in the before-image, so the saving in disk space due to binlog_row_value_options is limited to less than 50%.
1
noahlz

これはInnoDBとさらに関係があります

documentation で述べたように、テーブルのステータス

行の数。 MyISAMなどの一部のストレージエンジンは、正確な数を保存します。 InnoDBなどの他のストレージエンジンの場合、この値は概算値であり、実際の値と40%〜50%程度異なる場合があります。そのような場合は、SELECT COUNT(*)を使用して正確なカウントを取得してください。

したがって、COUNT(*)は正確な数を示します。

2
nbk

_analyze table tasks;_を使用して更新された統計を収集し、_show table status_がselect count(*) from tasksの値を反映しているかどうかを確認してください。 select count(*)は常に正確な値を返す必要がありますが、テーブル統計(_show table status_に表示)は最新ではない可能性があります。

0
Flourid