SQLに関するよくある質問

+9
q
d
l
O

このドキュメントでは、TiDB での SQL 操作に関する FAQ をまとめています。

TiDB はセカンダリキーをサポートしていますか?

はい。主キーではない列に、一意のセカンダリインデックス持つNOT NULL制約設定できます。この場合、その列はセカンダリキーとして機能します。

大きなテーブルで DDL 操作を実行する場合、TiDB はどのように機能しますか?

大規模なテーブルに対するTiDBのDDL操作は、通常は問題になりません。TiDBはオンラインDDL操作をサポートしており、これらのDDL操作はDML操作をブロックしません。

列の追加、列の削除、インデックスの削除などの一部の DDL 操作では、TiDB はこれらの操作を迅速に実行できます。

インデックスの追加など、一部の負荷の高いDDL操作では、TiDBはデータのバックフィルを行う必要があります。この処理には(テーブルのサイズに応じて)長い時間がかかり、追加のリソースを消費します。オンライントラフィックへの影響は調整可能です。TiDBは複数のスレッドでバックフィルを実行でき、消費されるリソースは以下のシステム変数によって設定できます。

適切なクエリプランを選択するにはどうすればよいですか?ヒントを使用する必要がありますか?それとも、ヒントを使用できますか?

TiDBにはコストベースのオプティマイザが搭載されています。ほとんどの場合、オプティマイザが最適なクエリプランを選択します。オプティマイザがうまく機能しない場合でも、 オプティマイザヒント使用してオプティマイザに介入することができます。

さらに、 SQLバインディング使用して、特定の SQL ステートメントのクエリ プランを修正することもできます。

特定の SQL ステートメントの実行を防ぐにはどうすればよいでしょうか?

TiDB v7.5.0以降のバージョンでは、 QUERY WATCHステートメントを使用して特定のSQL文を終了できます。詳細については、 予想よりも多くのリソースを消費するクエリ(ランナウェイクエリ)を管理する参照してください。

TiDB v7.5.0より前のバージョンでは、 MAX_EXECUTION_TIMEヒントを使用してSQLバインディング作成し、特定のステートメントの実行時間を小さな値(例えば1ミリ秒)に制限することができます。これにより、ステートメントはしきい値によって自動的に終了します。

たとえば、 SELECT * FROM t1, t2 WHERE t1.id = t2.idの実行を防ぐには、次の SQL バインディングを使用して、ステートメントの実行時間を 1 ミリ秒に制限できます。

CREATE GLOBAL BINDING for SELECT * FROM t1, t2 WHERE t1.id = t2.id USING SELECT /*+ MAX_EXECUTION_TIME(1) */ * FROM t1, t2 WHERE t1.id = t2.id;

注記:

MAX_EXECUTION_TIMEの精度は約100ミリ秒です。TiDBがSQL文を終了する前に、TiKV内のタスクが開始される場合があります。このような場合にTiKVのリソース消費を抑えるには、 tidb_enable_pagingからONに設定することをお勧めします。

この SQL バインディングを削除すると、制限が解除されます。

DROP GLOBAL BINDING for SELECT * FROM t1, t2 WHERE t1.id = t2.id;

TiDB と互換性のある MySQL 変数は何ですか?

システム変数参照。

ORDER BYを省略した場合、結果の順序はMySQLと異なります。

これはバグではありません。レコードのデフォルトの順序は様々な状況に依存し、一貫性は保証されません。

MySQLでは、クエリが単一スレッドで実行されるため、結果の順序は安定しているように見えるかもしれません。しかし、新しいバージョンにアップグレードすると、クエリプランが変更される場合があります。結果の順序を指定したい場合は、常にORDER BY使用することをお勧めします。

参照文献はISO/IEC 9075:1992、データベース言語 SQL - 1992年7月30日にあり、次のように述べられています。

<order by clause>が指定されていない場合、 <cursor specification>によって指定されたテーブルは T であり、T 内の行の順序は実装に依存します。

次の 2 つのクエリでは、両方の結果が正当であると見なされます。

> select * from t; +------+------+ | a | b | +------+------+ | 1 | 1 | | 2 | 2 | +------+------+ 2 rows in set (0.00 sec)
> select * from t; -- the order of results is not guaranteed +------+------+ | a | b | +------+------+ | 2 | 2 | | 1 | 1 | +------+------+ 2 rows in set (0.00 sec)

ORDER BYで使用されている列のリストが一意でない場合、この文も非決定的であるとみなされます。次の例では、列a重複した値があります。したがって、決定的であることが保証されるのはORDER BY a, bのみです。

> select * from t order by a; +------+------+ | a | b | +------+------+ | 1 | 1 | | 2 | 1 | | 2 | 2 | +------+------+ 3 rows in set (0.00 sec)

次のステートメントでは、列aの順序は保証されますが、 bの順序は保証されません。

> select * from t order by a; +------+------+ | a | b | +------+------+ | 1 | 1 | | 2 | 2 | | 2 | 1 | +------+------+ 3 rows in set (0.00 sec)

TiDB では、システム変数tidb_enable_ordered_result_mode使用して、最終出力結果を自動的にソートすることもできます。

TiDB はSELECT FOR UPDATEサポートしていますか?

はい。悲観的ロック(TiDB v3.0.8 以降のデフォルト)を使用する場合、 SELECT FOR UPDATE実行は MySQL と同様に動作します。

楽観的ロックを使用する場合、 SELECT FOR UPDATEトランザクションの開始時にデータをロックしませんが、トランザクションのコミット時に競合をチェックします。チェックで競合が見つかった場合、コミットしたトランザクションはロールバックされます。

詳細はSELECT構文要素の説明参照。

TiDBのコーデックは、UTF-8文字列がmemcomparableであることを保証できますか?キーがUTF-8をサポートする必要がある場合、コーディングに関する提案はありますか?

TiDBのデフォルトの文字セットはutf8mb4です。文字列はmemcomparable形式です。TiDBの文字セットの詳細については、 文字セットと照合順序参照してください。

トランザクション内のステートメントの最大数はいくつですか?

トランザクション内のステートメントの最大数は、デフォルトでは 5000 です。

楽観的トランザクション モードでトランザクションの再試行が有効になっている場合、デフォルトの上限は 5000 です。1 stmt-count-limitを使用して制限を調整できます。

TiDB で、後から挿入されたデータの自動増分 ID が、前に挿入されたデータの自動増分 ID よりも小さくなるのはなぜですか?

TiDBの自動増分ID機能は、自動的に増分され一意であることが保証されるだけで、連続的に割り当てられることは保証されません。現在、TiDBはIDをバッチで割り当てています。複数のTiDBサーバーに同時にデータが挿入された場合、割り当てられるIDは連続的ではありません。複数のスレッドがtidb-serverのインスタンスに同時にデータを挿入した場合、後で挿入されたデータの自動増分IDは小さくなる可能性があります。TiDBでは整数フィールドにAUTO_INCREMENT指定できますが、1つのテーブルにAUTO_INCREMENTフィールドは1つしか指定できません。詳細については、 自動増分IDAUTO_INCREMENT属性参照してください。

TiDB のsql_modeを変更するにはどうすればよいですか?

TiDB は、SESSION または GLOBAL ベースでsql_modeシステム変数を変更することをサポートしています。

  • GLOBALスコープの変数への変更は、クラスター内の残りのサーバーに伝播し、再起動後も保持されます。つまり、各 TiDBサーバーでsql_mode値を変更する必要はありません。
  • SESSIONスコープ変数への変更は、現在のクライアントセッションにのみ影響します。サーバーを再起動すると、変更は失われます。

エラー: java.sql.BatchUpdateException:statement count 5001 exceeds the transaction limitation

Sqoopでは、 --batch各バッチで100文をコミットすることを意味しますが、デフォルトでは各文に100個のSQL文が含まれます。つまり、100 * 100 = 10000文となり、これは単一のTiDBトランザクションで許可される文の最大数である5000を超えます。

2つの解決策:

  • 次のように-Dsqoop.export.records.per.statement=10オプションを追加します。

    sqoop export \ -Dsqoop.export.records.per.statement=10 \ --connect jdbc:mysql://mysql.example.com/sqoop \ --username sqoop ${user} \ --password ${passwd} \ --table ${tab_name} \ --export-dir ${dir} \ --batch
  • 単一のTiDBトランザクション内のステートメント数の制限を増やすこともできますが、これによりメモリ消費量が増加します。詳細についてはSQL文の制限参照してください。

TiDB には Oracle のフラッシュバック クエリのような機能がありますか? DDL をサポートしていますか?

はい、サポートしています。DDLもサポートしています。詳細はAS OF TIMESTAMP句を使用して履歴データを読み取るご覧ください。

TiDB はデータを削除した後すぐにスペースを解放しますか?

DELETE TRUNCATE操作DROPいずれもデータを即時に解放しません。7とTRUNCATE DROP操作では、TiDB GC(ガベージコレクション)時間(デフォルトでは10分)後にデータが削除され、領域が解放されます。11 DELETE操作では、データは削除されますが、圧縮が実行されるまで領域は即時に解放されません。

データを削除するとクエリ速度が遅くなるのはなぜですか?

大量のデータを削除すると、多くの無駄なキーが残り、クエリの効率に影響します。この問題を解決するには、 リージョン結合機能を使用できます。詳細については、 TiDBベストプラクティスのデータセクションの削除参照してください。

データを削除した後、storageスペースの回復に時間がかかる場合はどうすればよいでしょうか?

TiDBはマルチバージョン同時実行制御(MVCC)を使用しているため、古いデータが新しいデータで上書きされる際、古いデータは置き換えられず、新しいデータと共に保持されます。データのバージョンを識別するためにタイムスタンプが使用されます。データを削除しても、すぐに領域が解放されるわけではありません。同時実行トランザクションが以前のバージョンの行を参照できるように、ガベージコレクションは遅延されます。これは、システム変数tidb_gc_life_time (デフォルト: 10m0s )で設定できます。

SHOW PROCESSLISTシステム プロセス ID を表示しますか?

TiDB SHOW PROCESSLISTの表示内容は MySQL SHOW PROCESSLISTとほぼ同じです。TiDB SHOW PROCESSLISTではシステムプロセスIDが表示されません。表示されるのは現在のセッションIDです。TiDB SHOW PROCESSLISTと MySQL SHOW PROCESSLISTの違いは次のとおりです。

  • TiDBは分散データベースであるため、 tidb-serverインスタンスはSQL文を解析および実行するためのステートレスエンジンです(詳細はTiDBアーキテクチャ参照)。5 SHOW PROCESSLIST 、ユーザーがMySQLクライアントからログインしたtidb-serverインスタンスで実行されたセッションリストを表示します。クラスタ内で実行されているすべてのセッションのリストではありません。ただし、MySQLはスタンドアロンデータベースであり、 SHOW PROCESSLISTはMySQLで実行されたすべてのSQL文を表示します。
  • TiDBのState列目は、クエリ実行中に継続的に更新されるわけではありません。TiDBは並列クエリをサポートしているため、各ステートメントが複数の状態にある場合があり、単一の値に単純化することが困難です。

SQL コミットの実行優先度を制御または変更するにはどうすればよいですか?

TiDBは、 グローバル単位または個々のステートメント単位での優先度の変更をサポートしています。優先度は以下の意味を持ちます。

  • HIGH_PRIORITY : このステートメントの優先度は高いです。つまり、TiDB はこのステートメントを優先し、最初に実行します。

  • LOW_PRIORITY : このステートメントの優先度は低いです。つまり、TiDB は実行期間中にこのステートメントの優先度を下げます。

  • DELAYED : このステートメントは通常の優先度を持ち、 tidb_force_priorityNO_PRIORITY設定と同じです。

注記:

TiDB v6.6.0以降、 リソース管理サポートします。この機能を使用すると、異なるリソースグループで異なる優先度のSQL文を実行できます。これらのリソースグループに適切なクォータと優先度を設定することで、優先度の異なるSQL文のスケジュールをより適切に制御できます。リソース制御を有効にすると、文の優先度は適用されなくなります。異なるSQL文のリソース使用量を管理するには、 リソース管理使用することをお勧めします。

上記の2つのパラメータをTiDBのDMLと組み合わせて使用できます。例:

  1. データベースに SQL ステートメントを記述して優先順位を調整します。

    SELECT HIGH_PRIORITY | LOW_PRIORITY | DELAYED COUNT(*) FROM table_name; INSERT HIGH_PRIORITY | LOW_PRIORITY | DELAYED INTO table_name insert_values; DELETE HIGH_PRIORITY | LOW_PRIORITY | DELAYED FROM table_name; UPDATE HIGH_PRIORITY | LOW_PRIORITY | DELAYED table_reference SET assignment_list WHERE where_condition; REPLACE HIGH_PRIORITY | LOW_PRIORITY | DELAYED INTO table_name;
  2. フル テーブル スキャン ステートメントは、自動的に低い優先度に調整されます。 ANALYZE 、デフォルトで低い優先度を持ちます。

TiDB でのauto analyzeのトリガー戦略は何ですか?

テーブル内の行数またはパーティションテーブルの単一パーティションの行数が 1000 に達し、テーブルまたはパーティションの比率 (変更された行数 / 現在の行数の合計) がtidb_auto_analyze_ratioを超えると、 ANALYZEステートメントが自動的にトリガーされます。

システム変数tidb_auto_analyze_ratioのデフォルト値は0.5で、この機能がデフォルトで有効になっていることを示します。システム変数tidb_auto_analyze_ratiopseudo-estimate-ratio以上(デフォルト値は0.8 )に設定することは推奨されません。そうしないと、オプティマイザーが疑似統計を使用する可能性があります。TiDB v5.3.0 ではtidb_enable_pseudo_for_outdated_stats変数が導入され、これをOFFに設定すると、統計が古くても疑似統計は使用されません。

auto analyze無効にするには、システム変数tidb_enable_auto_analyze使用します。

オプティマイザーヒントを使用してオプティマイザーの動作をオーバーライドできますか?

TiDBは、 ヒントSQLプラン管理を含む、デフォルトのクエリオプティマイザの動作をオーバーライドする複数の方法をサポートしています。基本的な使用方法はMySQLと同様ですが、TiDB固有の拡張機能がいくつかあります。

SELECT column_name FROM table_name USE INDEX(index_name)WHERE where_condition;

DDL実行

このセクションでは、DDL文の実行に関連する問題を列挙します。DDL実行の原則に関する詳細な説明については、 DDL ステートメントの実行原則とベストプラクティス参照してください。

さまざまな DDL 操作を実行するにはどのくらいの時間がかかりますか?

DDL操作がブロックされておらず、各TiDBサーバーがスキーマバージョンを正常に更新でき、DDLオーナーノードが正常に動作していると仮定します。この場合、各種DDL操作の推定時間は以下のとおりです。

DDL操作タイプ推定所要時間
再編成DDL( ADD INDEXなどMODIFY COLUMN (再編成タイプのデータ変更)データ量、システム負荷、DDL パラメータ設定によって異なります。
一般ALTER TABLE DROPDROP TABLE (Reorg ALTER TABLE ADDDROP DATABASE CREATE TABLE )、 TRUNCATE TABLECREATE DATABASE (メタデータのみ変更) DROP INDEX MODIFY COLUMN約1秒

注記:

上記は作業にかかる推定時間です。実際の時間は異なる場合があります。

DDL実行が遅い理由

  • ユーザーセッションにおいて、DDL文の前に非自動コミットDML文があり、その非自動コミットDML文のコミット処理が遅い場合、DDL文の実行速度が低下します。つまり、TiDBはDDL文を実行する前に、コミットされていないDML文をコミットします。

  • 複数のDDL文を同時に実行する場合、後続のDDL文はキュー内で待機する必要があるため、実行速度が遅くなる可能性があります。キューイングのシナリオには以下が含まれます。

    • 同じ種類のDDL文はキューに登録する必要があります。例えば、 CREATE TABLECREATE DATABASEどちらも一般的なDDL文であるため、両方の操作が同時に実行される場合はキューに登録する必要があります。TiDB v6.2.0以降では並列DDL文がサポートされていますが、DDL実行にTiDBの計算リソースが過度に使用されるのを防ぐため、同時実行数制限も設けられています。DDL文が同時実行数制限を超えると、キューに登録されます。
    • 同じテーブルに対して実行されるDDL操作は依存関係にあります。後続のDDL文は、前のDDL操作が完了するまで待機する必要があります。
  • クラスターが正常に起動した後、DDL モジュールが DDL 所有者を選出するため、最初の DDL 操作の実行時間が比較的長くなる可能性があります。

  • TiDBが終了し、PDと正常に通信できなくなります(電源オフの状態も含む)。または、TiDBがコマンドkill -9によって終了し、PDから登録データを適切なタイミングで消去できなくなります。

  • クラスター内の特定の TiDB ノードと PD または TiKV の間で通信の問題が発生し、TiDB が最新のバージョン情報を時間内に取得できなくなります。

Information schema is changedエラーの原因は何ですか?

SQL文を実行する際、TiDBは分離レベルに基づいてオブジェクトのスキーマバージョンを決定し、それに応じてSQL文を処理します。TiDBはオンラインの非同期DDL変更もサポートしています。DML文を実行する際、複数のDDL文が同時に実行される可能性があり、各SQL文が同じスキーマに対して実行されるようにする必要があります。そのため、DML実行時にDDL操作が進行中の場合、TiDBはエラーInformation schema is changed報告する可能性があります。

v6.4.0 以降、TiDB はメタデータロックメカニズム実装しており、これにより DML ステートメントと DDL スキーマの変更の調整された実行が可能になり、ほとんどのInformation schema is changedエラーを回避できます。

このエラー報告には、まだいくつかの原因があります。

  • 原因1: DML操作に関係するテーブルの一部は、進行中のDDL操作に関係するテーブルと同じです。進行中のDDL操作を確認するには、 ADMIN SHOW DDLステートメントを使用してください。
  • 原因2:DML操作が長時間実行されています。この期間中に多数のDDL文が実行され、1024を超えるschemaバージョンの変更が発生しています。このデフォルト値は、変数tidb_max_delta_schema_count変更することで変更できます。
  • 原因3:DMLリクエストを受け付けるTiDBサーバーが長時間schema informationできない状態です(TiDBとPDまたはTiKV間の接続障害が原因と考えられます)。この期間中に多数のDDL文が実行され、100件を超えるschemaバージョンの変更が発生しました。
  • 原因 4: TiDB が再起動し、最初の DDL 操作が実行される前に、DML 操作が実行され、最初の DDL 操作に遭遇します (つまり、最初の DDL 操作が実行される前に、DML に対応するトランザクションが開始されます。そして、DDL の最初のschemaバージョンが変更された後、DML に対応するトランザクションがコミットされます)。この DML 操作によってこのエラーが報告されます。

上記の原因のうち、テーブルに関連するのは原因1のみです。原因1と原因2は、関連するDML操作が失敗後に再試行されるため、アプリケーションには影響しません。原因3については、TiDBとTiKV/PD間のネットワークを確認する必要があります。

注記:

  • 現在、TiDB はバージョンschemaの変更をすべてキャッシュしません。
  • 各 DDL 操作では、 schemaバージョンの変更の数は、対応するschema stateバージョンの変更の数と同じです。
  • DDL操作によって、バージョンschema変更回数は異なります。例えば、 CREATE TABLE文ではバージョンschema変更が1回発生し、 ADD COLUMN文ではバージョン5の変更が4回発生します。

「情報スキーマが古くなっています」というエラーの原因は何ですか?

DML文の実行時に、TiDBがDDLリース(デフォルトでは45秒)内に最新のスキーマをロードできない場合、エラーInformation schema is out of dateが発生する可能性があります。考えられる原因は以下のとおりです。

  • このDMLを実行したTiDBインスタンスが強制終了され、このDML文に対応するトランザクションの実行にDDLリースよりも長い時間がかかりました。トランザクションがコミットされた際にエラーが発生しました。
  • このDML文の実行中に、TiDBはPDまたはTiKVへの接続に失敗しました。その結果、TiDBはDDLリース内でスキーマのロードに失敗したか、キープアライブ設定によりPDから切断されました。

高い同時実行性で DDL ステートメントを実行するとエラーが報告されますか?

高い同時実行性で DDL ステートメント (バッチでのテーブル作成など) を実行すると、同時実行中のキーの競合により、これらのステートメントのごく一部が失敗する可能性があります。

同時実行 DDL ステートメントの数を 20 未満に保つことをお勧めします。それ以外の場合は、失敗したステートメントをクライアントから再試行する必要があります。

DDL 実行がブロックされるのはなぜですか?

TiDB v6.2.0より前のバージョンでは、DDL文の種類に基づいて、2つの先入先出キューにDDL文を割り当てていました。具体的には、再編成DDLは再編成キューに、一般DDLは一般キューに割り当てられます。先入先出の制限と、同一テーブルに対するDDL文の連続実行の必要性により、複数のDDL文が実行中にブロックされる可能性があります。

たとえば、次の DDL ステートメントを考えます。

  • DDL 1: CREATE INDEX idx on t(a int);
  • DDL 2: ALTER TABLE t ADD COLUMN b int;
  • DDL 3: CREATE TABLE t1(a int);

先入先出キューの制限により、DDL 3 は DDL 2 の実行を待機する必要があります。また、同じテーブル上の DDL 文はシリアルで実行する必要があるため、DDL 2 は DDL 1 の実行を待機する必要があります。そのため、DDL 3 と DDL 2 が異なるテーブルに対して実行される場合でも、DDL 3 は DDL 1 が先に実行されるまで待機する必要があります。

TiDB v6.2.0以降、TiDB DDLモジュールは並列フレームワークを採用しています。並列フレームワークでは、先入先出キューの制限がなくなりました。代わりに、TiDBはすべてのDDLタスクの中から実行可能なDDLタスクを選択します。さらに、Reorgワーカーの数がノードあたり約CPU/4に拡張されました。これにより、TiDBは並列フレームワーク内で複数のテーブルのインデックスを同時に構築できます。

新規クラスタでも、以前のバージョンからアップグレードしたクラスタでも、TiDB v6.2以降のバージョンでは、TiDBは自動的にコンカレントフレームワークを使用します。手動で調整する必要はありません。

DDL実行のスタックの原因を特定する

  1. DDL ステートメントの実行が遅くなる他の理由を排除します。
  2. DDL 所有者ノードを識別するには、次のいずれかの方法を使用します。
    • 現在のクラスターの所有者を取得するには、 curl http://{TiDBIP}:10080/info/all使用します。
    • 監視ダッシュボードのDDL > DDL META OPMから、特定の期間の所有者をビュー。
  • 所有者が存在しない場合は、次を実行して所有者の選択を手動でトリガーしてみてください: curl -X POST http://{TiDBIP}:10080/ddl/owner/resign
  • 所有者が存在する場合は、Goroutine スタックをエクスポートし、スタックしている可能性のある場所を確認します。

JDBC接続で使用される照合順序

このセクションでは、JDBC接続で使用される照合順序に関する質問を示します。TiDBでサポートされている文字セットと照合順序については、 文字セットと照合順序参照してください。

JDBC URL でconnectionCollationが構成されていない場合、JDBC 接続ではどの照合順序が使用されますか?

JDBC URL にconnectionCollationが設定されていない場合、次の 2 つのシナリオが考えられます。

シナリオ 1 : JDBC URL にconnectionCollationcharacterEncoding設定されていない

  • Connector/J 8.0.25以前のバージョンでは、JDBCドライバはサーバーのデフォルトの文字セットを使用しようとします。TiDBのデフォルトの文字セットはutf8mb4であるため、ドライバは接続照合順序としてutf8mb4_bin使用します。

  • Connector/J 8.0.26 以降のバージョンでは、JDBC ドライバーはutf8mb4文字セットを使用し、戻り値SELECT VERSION()に基づいて照合順序を自動的に選択します。

    • 戻り値が8.0.1未満の場合、ドライバは接続照合順序としてutf8mb4_general_ci使用します。TiDB はドライバに従い、照合順序としてutf8mb4_general_ci使用します。
    • 戻り値が8.0.1以上の場合、ドライバは接続照合順序としてutf8mb4_0900_ai_ci使用します。TiDB v7.4.0 以降のバージョンではドライバに従い、照合順序としてutf8mb4_0900_ai_ci使用しますが、TiDB v7.4.0 より前のバージョンではutf8mb4_0900_ai_ci照合順序がサポートされていないため、デフォルトの照合順序utf8mb4_bin使用されます。

シナリオ2 :JDBC URLにcharacterEncoding=utf8が設定されていますが、 connectionCollation設定されていません。JDBCドライバーはマッピングルールに従ってutf8mb4文字セットを使用します。照合順序はシナリオ1で説明したルールに従って決定されます。

TiDB をアップグレードした後、照合順序の変更をどのように処理しますか?

TiDB v7.4 以前のバージョンでは、 connectionCollationが構成されておらず、JDBC URL でcharacterEncoding構成されていないかUTF-8に設定されている場合、TiDB collation_connection変数はデフォルトでutf8mb4_bin照合順序に設定されます。

TiDB v7.4以降、 connectionCollationが設定されておらず、JDBC URLでcharacterEncoding設定されていないかUTF-8に設定されている場合、 collation_connection変数の値はJDBCドライバのバージョンによって異なります。例えば、Connector/J 8.0.26以降のバージョンでは、JDBCドライバはデフォルトでutf8mb4文字セットを使用し、接続照合順序としてutf8mb4_general_ci使用します。TiDBはドライバに従い、 collation_connection変数はutf8mb4_0900_ai_ci照合順序を使用します。詳細については、 JDBC接続で使用される照合順序参照してください。

以前のバージョンから v7.4 以降にアップグレードする場合 (たとえば、v6.5 から v7.5)、JDBC 接続でcollation_connection utf8mb4_binとして維持する必要がある場合は、JDBC URL でconnectionCollationパラメータを構成することをお勧めします。

以下は、TiDB v6.5 での一般的な JDBC URL 構成です。

spring.datasource.url=JDBC:mysql://{TiDBIP}:{TiDBPort}/{DBName}?characterEncoding=UTF-8&useSSL=false&useServerPrepStmts=true&cachePrepStmts=true&prepStmtCacheSqlLimit=10000&prepStmtCacheSize=1000&useConfigs=maxPerformance&rewriteBatchedStatements=true&defaultfetchsize=-2147483648&allowMultiQueries=true

TiDB v7.5 以降のバージョンにアップグレードした後は、JDBC URL にconnectionCollationパラメータを設定することをお勧めします。

spring.datasource.url=JDBC:mysql://{TiDBIP}:{TiDBPort}/{DBName}?characterEncoding=UTF-8&connectionCollation=utf8mb4_bin&useSSL=false&useServerPrepStmts=true&cachePrepStmts=true&prepStmtCacheSqlLimit=10000&prepStmtCacheSize=1000&useConfigs=maxPerformance&rewriteBatchedStatements=true&defaultFetchSize=-2147483648&allowMultiQueries=true

utf8mb4_binutf8mb4_0900_ai_ci照合順序の違いは何ですか?

照合大文字と小文字を区別末尾のスペースを無視するアクセントを重視比較方法
utf8mb4_binはいはいはいバイナリ値を比較する
utf8mb4_0900_ai_ciいいえいいえいいえUnicodeソートアルゴリズムを使用する

例えば:

-- utf8mb4_bin is case-sensitive SELECT 'apple' = 'Apple' COLLATE utf8mb4_bin; -- Returns 0 (FALSE) -- utf8mb4_0900_ai_ci is case-insensitive SELECT 'apple' = 'Apple' COLLATE utf8mb4_0900_ai_ci; -- Returns 1 (TRUE) -- utf8mb4_bin ignores trailing spaces SELECT 'Apple ' = 'Apple' COLLATE utf8mb4_bin; -- Returns 1 (TRUE) -- utf8mb4_0900_ai_ci does not ignore trailing spaces SELECT 'Apple ' = 'Apple' COLLATE utf8mb4_0900_ai_ci; -- Returns 0 (FALSE) -- utf8mb4_bin is accent-sensitive SELECT 'café' = 'cafe' COLLATE utf8mb4_bin; -- Returns 0 (FALSE) -- utf8mb4_0900_ai_ci is accent-insensitive SELECT 'café' = 'cafe' COLLATE utf8mb4_0900_ai_ci; -- Returns 1 (TRUE)

SQL最適化

TiDB実行プランの説明

クエリ実行プランを理解する参照。

統計収集

統計入門参照。

select count(1)を最適化するにはどうすればいいですか?

count(1)文はテーブル内の行の総数をカウントします。同時実行性を向上させることで、速度を大幅に向上させることができます。同時実行性を変更するには、 tidb_distsql_scan_concurrencyドキュメントを参照してください。ただし、これはCPUとI/Oリソースにも依存します。TiDBはすべてのクエリでTiKVにアクセスします。データ量が少ない場合、MySQLはすべてメモリ内に保存されるため、TiDBはネットワークアクセスを実行する必要があります。

推奨事項:

現在の DDL ジョブの進行状況を表示するにはどうすればよいでしょうか?

ADMIN SHOW DDL使用すると、現在の DDL ジョブの進行状況を表示できます。操作は以下のとおりです。

ADMIN SHOW DDL;
*************************** 1. row *************************** SCHEMA_VER: 140 OWNER: 1a1c4174-0fcd-4ba0-add9-12d08c4077dc RUNNING_JOBS: ID:121, Type:add index, State:running, SchemaState:write reorganization, SchemaID:1, TableID:118, RowCount:77312, ArgLen:0, start time: 2018-12-05 16:26:10.652 +0800 CST, Err:<nil>, ErrCount:0, SnapshotVersion:404749908941733890 SELF_ID: 1a1c4174-0fcd-4ba0-add9-12d08c4077dc

上記の結果から、 ADD INDEX操作が現在処理中であることがわかります。また、 RUNNING_JOBS列目のRowCount番目のフィールドから、 ADD INDEX操作によって77312行のインデックスが追加されたことがわかります。

DDL ジョブを表示するにはどうすればいいですか?

  • ADMIN SHOW DDL : 実行中のDDLジョブを表示する
  • ADMIN SHOW DDL JOBS : 現在の DDL ジョブ キュー内のすべての結果 (実行中および実行待ちのタスクを含む) と、完了した DDL ジョブ キューの最後の 10 件の結果を表示します。
  • ADMIN SHOW DDL JOBS QUERIES 'job_id' [, 'job_id'] ... : job_idに対応する DDL タスクの元の SQL ステートメントを表示します。4 job_id実行中の DDL ジョブと DDL 履歴ジョブ キュー内の最後の 10 件の結果のみを検索します。

TiDB は CBO (コストベース最適化) をサポートしていますか? サポートしている場合、どの程度サポートしていますか?

はい。TiDBはコストベースオプティマイザを使用しています。コストモデルと統計は常に最適化されています。また、TiDBはハッシュ結合やソートマージ結合などの結合アルゴリズムもサポートしています。

テーブルでanalyzeを実行する必要があるかどうかを判断するにはどうすればよいでしょうか?

SHOW STATS_HEALTHYを使用してHealthyフィールドをビュー、通常、フィールド値が 60 より小さい場合はテーブルでANALYZE実行する必要があります。

クエリプランがツリーとして表現される場合のIDルールは何ですか?このツリーの実行順序は何ですか?

これらのIDにはルールはありませんが、IDは一意です。IDが生成されるとカウンターが動作し、プランが1つ生成されるごとに1が加算されます。実行順序はIDとは無関係です。クエリプラン全体はツリー構造になっており、実行プロセスはルートノードから開始され、データは上位レベルへと連続的に返されます。クエリプランの詳細については、 TiDBクエリ実行プランを理解する参照してください。

TiDBクエリプランでは、 copタスクは同じルートにあります。それらは同時に実行されますか?

現在、 TiDB のコンピューティング タスクは、タスクcop taskroot task 2 つの異なるタイプに属しています。

cop taskは、分散実行のために KV エンドにプッシュダウンされるコンピューティング タスクです。2 root task 、TiDB エンドでの単一ポイント実行のためのコンピューティング タスクです。

通常、 root taskの入力データはcop taskから取得されます。5 root taskデータを処理している間、TiKVのcop task同時にデータを処理し、TiDBのroot taskからのプルを待機します。したがって、 copタスクはroot taskと並行して実行されていると見なすことができますが、それらのデータには上流と下流の関係があります。実行プロセス中、それらはしばらくの間並行して実行されます。たとえば、最初のcop task[100, 200]のデータを処理し、2番目のcop task [1, 100]のデータを処理します。詳細はTiDBクエリプランの理解参照してください。

データベースの最適化

TiDBオプションを編集する

TiDBコマンドオプション参照。

ホットスポットの問題を回避し、負荷分散を実現するにはどうすればよいですか? TiDB ではホット パーティションまたはホット範囲が問題になりますか?

ホットスポットが発生するシナリオについては、 一般的な鍋料理を参照してください。次の TiDB 機能は、ホットスポットの問題を解決するために設計されています。

  • SHARD_ROW_ID_BITS属性。この属性を設定すると、行IDが複数のリージョンに分散して書き込まれるため、書き込みホットスポットの問題を軽減できます。
  • AUTO_RANDOM属性は、自動インクリメント主キーによってもたらされるホットスポットを解決するのに役立ちます。
  • コプロセッサーキャッシュ 、小さなテーブル上の読み取りホットスポットの場合。
  • ロードベーススプリット 、小さなテーブルの完全なテーブルスキャンなど、リージョン間の不均衡なアクセスによって発生するホットスポットの場合。
  • キャッシュされたテーブル 、頻繁にアクセスされるが、めったに更新されない小さなホットスポット テーブル用。

ホットスポットによってパフォーマンスの問題が発生した場合は、 ホットスポットの問題のトラブルシューティングを参照して解決してください。

TiKV のパフォーマンスを調整する

TiKV スレッドのパフォーマンスを調整するTiKVメモリのパフォーマンスを調整する参照してください。

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