データの挿入

このドキュメントでは、SQL 言語とさまざまなプログラミング言語を使用して TiDB にデータを挿入する方法について説明します。

始める前に

このドキュメントを読む前に、以下を準備する必要があります。

行の挿入

複数行のデータを挿入するには 2 つの方法があります。たとえば、 3人のプレイヤーのデータを挿入する必要がある場合です。

  • 複数行の挿入ステートメント:

    INSERT INTO `player` (`id`, `coins`, `goods`) VALUES (1, 1000, 1), (2, 230, 2), (3, 300, 5);
  • 複数の単一行挿入ステートメント:

    INSERT INTO `player` (`id`, `coins`, `goods`) VALUES (1, 1000, 1); INSERT INTO `player` (`id`, `coins`, `goods`) VALUES (2, 230, 2); INSERT INTO `player` (`id`, `coins`, `goods`) VALUES (3, 300, 5);

一般に、 multi-line insertion statement​​倍数のsingle-line insertion statementsよりも高速に実行されます。

  • SQL
  • Java
  • Golang
  • Python
CREATE TABLE `player` (`id` INT, `coins` INT, `goods` INT); INSERT INTO `player` (`id`, `coins`, `goods`) VALUES (1, 1000, 1), (2, 230, 2);

この SQL の使用方法の詳細については、 TiDBクラスタへの接続を参照し、クライアントを使用して TiDB クラスターに接続した後、手順に従って SQL ステートメントを入力します。

// ds is an entity of com.mysql.cj.jdbc.MysqlDataSource try (Connection connection = ds.getConnection()) { connection.setAutoCommit(false); PreparedStatement pstmt = connection.prepareStatement("INSERT INTO player (id, coins, goods) VALUES (?, ?, ?)")) // first player pstmt.setInt(1, 1); pstmt.setInt(2, 1000); pstmt.setInt(3, 1); pstmt.addBatch(); // second player pstmt.setInt(1, 2); pstmt.setInt(2, 230); pstmt.setInt(3, 2); pstmt.addBatch(); pstmt.executeBatch(); connection.commit(); } catch (SQLException e) { e.printStackTrace(); }

デフォルトの MySQL JDBCDriver設定により、一括挿入のパフォーマンスを向上させるには、いくつかのパラメーターを変更する必要があります。

パラメータ手段推奨シナリオ推奨されるコンフィグレーション
useServerPrepStmtsサーバー側を使用してプリペアドステートメントを有効にするかどうかプリペアドステートメントを複数回使用する必要がある場合true
cachePrepStmtsクライアントが準備されたステートメントをキャッシュするかどうかuseServerPrepStmts=truetrue
prepStmtCacheSqlLimitプリペアドステートメントの最大サイズ (デフォルトでは 256 文字)プリペアドステートメントが 256 文字を超える場合プリペアドステートメントの実際のサイズに応じて構成されます
prepStmtCacheSizeプリペアドステートメントキャッシュの最大数 (デフォルトでは 25)準備されたステートメントの数が 25 を超える場合実際の準備済みステートメントの数に応じて構成されます
rewriteBatchedStatementsBatchedステートメントを書き換えるかどうかバッチ操作が必要な場合true
allowMultiQueriesバッチ操作を開始するクライアントのバグrewriteBatchedStatements = trueuseServerPrepStmts = trueのときにこれを設定する必要があるためtrue

MySQL JDBC Driver は、 useConfigs統合構成も提供します。 maxPerformanceで構成すると、一連の構成を構成することと同じになります。 mysql:mysql-connector-java:8.0.28例にとると、 useConfigs=maxPerformanceには次のものが含まれます。

cachePrepStmts=true cacheCallableStmts=true cacheServerConfiguration=true useLocalSessionState=true elideSetAutoCommits=true alwaysSendSetIsolation=false enableQueryTimeouts=false connectionAttributes=none useInformationSchema=true

mysql-connector-java-{version}.jar!/com/mysql/cj/configurations/maxPerformance.propertiesをチェックすると、MySQL JDBC Driverの対応するバージョンのuseConfigs=maxPerformanceに含まれる構成を取得できます。

以下は、JDBC 接続文字列構成の一般的なシナリオです。この例では、ホスト: 127.0.0.1 、ポート: 4000 、ユーザー名: root 、パスワード: null、デフォルトのデータベース: test :

jdbc:mysql://127.0.0.1:4000/test?user=root&useConfigs=maxPerformance&useServerPrepStmts=true&prepStmtCacheSqlLimit=2048&prepStmtCacheSize=256&rewriteBatchedStatements=true&allowMultiQueries=true

Javaの完全な例については、以下を参照してください。

package main import ( "database/sql" "strings" _ "github.com/go-sql-driver/mysql" ) type Player struct { ID string Coins int Goods int } func bulkInsertPlayers(db *sql.DB, players []Player, batchSize int) error { tx, err := db.Begin() if err != nil { return err } stmt, err := tx.Prepare(buildBulkInsertSQL(batchSize)) if err != nil { return err } defer stmt.Close() for len(players) > batchSize { if _, err := stmt.Exec(playerToArgs(players[:batchSize])...); err != nil { tx.Rollback() return err } players = players[batchSize:] } if len(players) != 0 { if _, err := tx.Exec(buildBulkInsertSQL(len(players)), playerToArgs(players)...); err != nil { tx.Rollback() return err } } if err := tx.Commit(); err != nil { tx.Rollback() return err } return nil } func playerToArgs(players []Player) []interface{} { var args []interface{} for _, player := range players { args = append(args, player.ID, player.Coins, player.Goods) } return args } func buildBulkInsertSQL(amount int) string { return "INSERT INTO player (id, coins, goods) VALUES (?, ?, ?)" + strings.Repeat(",(?,?,?)", amount-1) }

Golangの完全な例については、以下を参照してください。

import MySQLdb connection = MySQLdb.connect( host="127.0.0.1", port=4000, user="root", password="", database="bookshop", autocommit=True ) with get_connection(autocommit=True) as connection: with connection.cursor() as cur: player_list = random_player(1919) for idx in range(0, len(player_list), 114): cur.executemany("INSERT INTO player (id, coins, goods) VALUES (%s, %s, %s)", player_list[idx:idx + 114])

Python の完全な例については、以下を参照してください。

一括挿入

大量のデータを TiDB クラスターに迅速にインポートする必要がある場合は、データ移行用にPingCAPが提供するさまざまなツールを使用することをお勧めします。 INSERTステートメントの使用は、効率的ではなく、例外やその他の問題を自分で処理する必要があるため、最良の方法ではありません。

一括挿入に推奨されるツールは次のとおりです。

  • データのエクスポート: Dumpling . MySQL または TiDB データをローカルまたは Amazon S3 にエクスポートできます。
  • データインポート: TiDB Lightning . Dumpling のエクスポート データ、 CSVファイル、またはAmazon Auroraから TiDB へのデータの移行をインポートできます。ローカル ディスクまたは Amazon S3 クラウド ディスクからのデータの読み取りもサポートします。
  • データ複製: TiDB データ移行 。 MySQL、MariaDB、Amazon Auroraデータベースを TiDB にレプリケートできます。また、ソース データベースからのシャード化されたインスタンスとテーブルのマージと移行もサポートします。
  • データのバックアップと復元: バックアップと復元 (BR) . Dumplingと比較して、 BR は***ビッグデータの***シナリオにより適しています。
  • データインポート: TiDB Cloudコンソールインポートの作成ページ。 Dumpling のエクスポート データをインポートしたり、ローカルのCSVファイルをインポートしたり、 Amazon S3 または GCS からTiDB Cloudに CSV ファイルをインポート実行したりできます。ローカル ディスク、Amazon S3 クラウド ディスク、または GCS クラウド ディスクからのデータの読み取りもサポートします。
  • データ複製: TiDB データ移行 。 MySQL、MariaDB、Amazon Auroraデータベースを TiDB にレプリケートできます。また、ソース データベースからのシャード化されたインスタンスとテーブルのマージと移行もサポートします。
  • データのバックアップと復元: TiDB Cloudコンソールのバックアップページ。 Dumplingと比較して、バックアップと復元はビッグ データのシナリオにより適しています。

ホットスポットを避ける

テーブルを設計するときは、多数の挿入操作があるかどうかを考慮する必要があります。その場合、テーブルの設計中にホットスポットを回避する必要があります。 主キーを選択セクションを参照し、 主キーを選択する際のルールに従ってください。

ホットスポットの問題の処理方法の詳細については、 ホットスポットの問題のトラブルシューティングを参照してください。

AUTO_RANDOM主キーを使用してテーブルにデータを挿入する

挿入するテーブルの主キーにAUTO_RANDOM属性がある場合、デフォルトでは主キーを指定できません。たとえば、データベースbookshopでは、 usersテーブルidフィールドにAUTO_RANDOM属性が含まれていることがわかります。

この場合、次のような SQL を使用して挿入することはできません

INSERT INTO `bookshop`.`users` (`id`, `balance`, `nickname`) VALUES (1, 0.00, 'nicky');

エラーが発生します:

ERROR 8216 (HY000): Invalid auto random: Explicit insertion on auto_random column is disabled. Try to set @@allow_auto_random_explicit_insert = true.

挿入時にAUTO_RANDOM列を手動で指定することはお勧めできません。

このエラーを処理するには 2 つの解決策があります。

  • (推奨) この列を挿入ステートメントから削除し、TiDB が初期化した値AUTO_RANDOMを使用します。これはAUTO_RANDOMのセマンティクスに適合します。

    INSERT INTO `bookshop`.`users` (`balance`, `nickname`) VALUES (0.00, 'nicky');
  • この列を指定する必要があることが確実な場合は、ユーザー変数を変更することで、 SETステートメント使用して挿入時にAUTO_RANDOMの列を指定できるようにすることができます。

    SET @@allow_auto_random_explicit_insert = true; INSERT INTO `bookshop`.`users` (`id`, `balance`, `nickname`) VALUES (1, 0.00, 'nicky');

HTAP を使用する

TiDB では、HTAP 機能により、データの挿入時に追加の操作を実行する必要がなくなります。追加の挿入ロジックはありません。 TiDB はデータの一貫性を自動的に保証します。テーブルを作成した後、列指向レプリカ列指向のレプリカ同期を有効にする使用してクエリを直接高速化するだけです。

このページは役に立ちましたか?

Playground
新規
登録なしで TiDB の機能をワンストップでインタラクティブに体験できます。
製品
TiDB Cloud
TiDB
価格
PoC お問い合わせ
エコシステム
TiKV
TiFlash
OSS Insight
© 2024 PingCAP. All Rights Reserved.
Privacy Policy.