8

UTF8 MySQL 5.5.30 データベースを UTF8MB4 に変換しようとしています。この記事https://mathiasbynens.be/notes/mysql-utf8mb4を見ましたが、いくつか質問があります。

私はこれらをやった

ALTER DATABASE database_name CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci;
ALTER TABLE table_name CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

最後の1つは62のテーブルで手動で行われ、そのうちの1つがこの警告を出しました

13:08:30 ALTER TABLE bradspelold.games CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci 101289 行が影響を受け、2 つの警告: 1071 指定されたキーが長すぎました。キーの最大長は 767 バイトです。 1071 指定されたキーが長すぎます。キーの最大長は 767 バイト レコード: 101289 重複: 0 警告: 2 3.016 秒

  1. これは問題ですか?修正するにはどうすればよいですか?

次のステップは

ALTER TABLE table_name CHANGE column_name column_name
         VARCHAR(191) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
  1. コマンドについてよくわかりません。なぜ column_name が 2 つあるのですか?
  2. VARCHAR(191) 列でのみこれを行う必要がありますか? 私はそれらのいずれかを持っているとは思いませんか?
  3. このような id の詳細について、その理由と方法を説明している記事を他に知っていますか?

編集 :

テーブルショーゲーム

CREATE  TABLE `games` (
        `id` int(10) unsigned NOT NULL DEFAULT \'0\',
        `name` varchar(255) NOT NULL,
        `description` mediumtext,
        `yearPublished` datetime NOT NULL,
        `minPlayers` int(10) unsigned NOT NULL,
        `maxPlayers` int(10) unsigned NOT NULL,
        `playingTime` varchar(127) NOT NULL,
        `grade` double NOT NULL DEFAULT \'0\',
        `updated` datetime NOT NULL,
        `forumParentId` int(10) unsigned DEFAULT \'0\',
        `lastVisited` datetime DEFAULT NULL,
        `inactivatedDate` datetime DEFAULT NULL,
        `bggGrade` double DEFAULT NULL,
        PRIMARY KEY (`id`),
        KEY `inactivatedDate` (`inactivatedDate`),
        KEY `name` (`name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8'

編集2:

    'CREATE TABLE `forum_threads` (
      `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
      `title` varchar(150) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '''',
      `description` varchar(150) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '''',
      `createdDate` datetime NOT NULL DEFAULT ''0000-00-00 00:00:00'',
      `createrId` int(10) unsigned DEFAULT NULL,
      `replys` int(10) unsigned NOT NULL DEFAULT ''0'',
      `lastPostUserId` int(10) unsigned DEFAULT NULL,
      `lastPostId` int(10) unsigned DEFAULT NULL,
      `forumId` int(10) unsigned DEFAULT NULL,
      `visits` int(10) unsigned NOT NULL DEFAULT ''0'',
      `lastPostCreated` datetime NOT NULL DEFAULT ''0000-00-00 00:00:00'',
      `lastPostNickName` varchar(30) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '''',
      `createrNickName` varchar(30) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '''',
      `solved` tinyint(1) NOT NULL DEFAULT ''0'',
      `locked` tinyint(1) NOT NULL DEFAULT ''0'',
      `lockedByUserId` int(10) unsigned NOT NULL DEFAULT ''0'',
      `lockedDate` datetime NOT NULL DEFAULT ''0000-00-00 00:00:00'',
      `alteredDate` datetime NOT NULL DEFAULT ''0000-00-00 00:00:00'',
      `alteredUserId` int(10) unsigned DEFAULT NULL,
      `glued` tinyint(1) NOT NULL DEFAULT ''0'',
      `pollId` int(10) unsigned DEFAULT NULL,
      `facebookPostId` bigint(20) DEFAULT NULL,
      `facebookImportedDate` datetime DEFAULT NULL,
      PRIMARY KEY (`id`),
      KEY `FK_forum_threads_1` (`forumId`),
      KEY `FK_forum_threads_2` (`pollId`),
      KEY `createdDate` (`createdDate`),
      KEY `createrId` (`createrId`),
      KEY `lastPostCreated` (`lastPostCreated`),
      CONSTRAINT `FK_forum_threads_1` FOREIGN KEY (`forumId`) REFERENCES `forum` (`id`) ON DELETE CASCADE
    ) ENGINE=InnoDB AUTO_INCREMENT=4306 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci'

'CREATE TABLE `forum` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `title` varchar(80) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '''',
  `description` varchar(150) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '''',
  `createdDate` datetime NOT NULL DEFAULT ''0000-00-00 00:00:00'',
  `threads` int(10) unsigned NOT NULL DEFAULT ''0'',
  `createrId` int(10) unsigned DEFAULT NULL,
  `lastPostUserId` int(10) unsigned DEFAULT NULL,
  `lastThreadId` int(10) unsigned DEFAULT NULL,
  `parentForumId` int(10) unsigned DEFAULT NULL,
  `lastPostNickName` varchar(30) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '''',
  `lastPostCreated` datetime NOT NULL DEFAULT ''0000-00-00 00:00:00'',
  `lastThreadTitle` varchar(80) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '''',
  `alteredDate` datetime NOT NULL DEFAULT ''0000-00-00 00:00:00'',
  `alteredUserId` int(10) unsigned DEFAULT NULL,
  `placeOrder` int(10) unsigned NOT NULL DEFAULT ''0'',
  `separator` tinyint(1) NOT NULL DEFAULT ''0'',
  `rightLevel` int(10) unsigned NOT NULL DEFAULT ''1'',
  `createChildForum` tinyint(3) unsigned NOT NULL DEFAULT ''1'',
  `createThreads` tinyint(3) unsigned NOT NULL DEFAULT ''1'',
  PRIMARY KEY (`id`),
  KEY `Index_1` (`id`,`parentForumId`)
) ENGINE=InnoDB AUTO_INCREMENT=375 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci'
4

3 に答える 3

5
  1. INDEX のサイズには制限があります。utf8mb4 は文字あたり最大 4バイトを必要とするのに対し、utf8 は 3 しか必要としないため、制限にぶつかりました。一方、INDEX サイズの制限はバイト単位です。

「解決策」は、大きすぎるインデックスをどうするかを決定することです。(詳細は以下)

2.

ALTER TABLE t CHANGE col col ...

より論理的なものと同じです

ALTER TABLE t MODIFY col ...

前者では列の名前を変更できるため、名前を変更する必要がない場合は列名の 2 つのコピーが必要です。

  1. VARCHAR(255)utf8 で 767 バイト (3*255+2; "2" は長さフィールドのサイズ) を必要とする可能性が非常に高いです。4 バイトの utf8mb4 に相当するものは (191) (4*191+2=766; 191 を超える余地はありません) です。

  2. 私はそれについての記事を見たことがありません。私が今言ったことは、言う必要があることのほとんどだと思います。

そう...

プランA :foo VARCHAR(255)ありますか? utf8 でしたか? その中のデータは常に (現在も将来も) 191 文字より短いですか? その場合は、単純に ALTER を実行してください。

プランB : 191 以上必要な場合、INDEX は本当に必要ですか? DROP INDEX が代替手段になる場合があります。

プランC : または、「接頭辞」 index: を使用して、 INDEX(foo(191))それをそのままにしておくこともできますVARCHAR(255)。通常、「プレフィックス」インデックスは役に立ちませんが、それが機能するユースケースがあるかもしれません。

これについてさらに議論するSHOW CREATE TABLEには、問題のテーブルを提供し、その特定のフィールドとその INDEX の意味について議論してください。

于 2015-03-23T05:28:31.500 に答える
2

これは古い質問ですが、5年後にここでいくつかの回答に従うことは、私が発見したように、悪い考えです. フィールドのサイズを変更しないでくださいVARCHAR。データが破損し、すべてが壊れる可能性があります。

MySQL と MaraiDB の現在のバージョンでは、これを構成に追加すると、UTF8mb4 に必要なより大きなキーがサポートされます。

innodb_large_prefix=1

追加することもお勧めします innodb_file_per_table =1 innodb_file_format=Barracuda

その後、キーの長さに関するエラー/警告なしで変換が行われます

于 2019-06-18T19:02:07.680 に答える