重要
このページは英語版のページを機械翻訳しています。原文はこちらからご覧ください。

SQLに関するFAQ

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

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)
> select * from t order by a; -- the order of column a is guaranteed, but b is not
+------+------+
| a    | b    |
+------+------+
|    1 |    1 |
|    2 |    2 |
|    2 |    1 |
+------+------+
3 rows in set (0.00 sec)

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

はい。ペシミスティックロック(TiDB v3.0以降のデフォルト)を使用する場合、 SELECT FOR UPDATEの実行はMySQLと同様に動作します。

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

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

TiDBはデフォルトでUTF-8文字セットを使用し、現在はUTF-8のみをサポートしています。 TiDBの文字列は、memcomparable形式を使用します。

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

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

後で挿入されたデータの自動インクリメントIDが、TiDBに以前に挿入されたデータの自動インクリメントIDよりも小さいのはなぜですか?

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

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

TiDBは、SESSIONまたはGLOBALベースでsql_modeのシステム変数の変更をサポートします。 GLOBALのスコープ変数への変更は、クラスタの残りのサーバーに伝播し、再起動後も保持されます。これは、各TiDBサーバーでsql_modeの値を変更する必要がないことを意味します。

エラー: java.sql.BatchUpdateExecption:statement count 5001 exceeds the transaction limitationます

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

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
    
  • 1つのTiDBトランザクションで制限された数のステートメントを増やすこともできますが、これはより多くのメモリを消費します。

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

はい、そうです。また、DDLもサポートしています。詳細については、 TiDBが履歴バージョンからデータを読み取る方法を参照してください。

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

DELETE 、およびTRUNCATEの操作のいずれも、データをすぐに解放しませDROPTRUNCATEおよびDROPの操作では、TiDB GC(ガベージコレクション)時間(デフォルトでは10分)の後、データが削除され、スペースが解放されます。 DELETE回の操作では、データは削除されますが、圧縮が実行されるまでスペースはすぐには解放されません。

データが削除された後、クエリ速度が遅くなるのはなぜですか?

大量のデータを削除すると、多くの役に立たないキーが残り、クエリの効率に影響します。現在、 リージョンマージつの機能が開発中であり、この問題の解決が期待されています。詳細については、 TiDBベストプラクティスのデータセクションの削除を参照してください。

データを削除した後にストレージスペースを再利用するのが遅い場合はどうすればよいですか?

TiDBはマルチバージョン同時実行制御(MVCC)を使用するため、データを削除してもすぐにスペースが再利用されるわけではありません。ガベージコレクションは、同時トランザクションが以前のバージョンの行を表示できるように遅延されます。これは、 tidb_gc_life_time (デフォルト: 10m0s )システム変数を介して構成できます。

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

TiDB1の表示内容はSHOW PROCESSLISTの表示内容とほぼ同じSHOW PROCESSLISTshow processlistはシステムプロセスIDを表示しません。表示されるIDは、現在のセッションIDです。 show processlistshow processlistの違いは次のとおりです。

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

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

グローバル セッションごとまたは個別のステートメントに基づいて優先度を変更することをサポートしています。優先度には次の意味があります。

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

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

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

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

    select HIGH_PRIORITY | LOW_PRIORITY count(*) from table_name;
    insert HIGH_PRIORITY | LOW_PRIORITY into table_name insert_values;
    delete HIGH_PRIORITY | LOW_PRIORITY from table_name;
    update HIGH_PRIORITY | LOW_PRIORITY table_reference set assignment_list where where_condition;
    replace HIGH_PRIORITY | LOW_PRIORITY into table_name;
    
  2. 全表スキャンステートメントは、自動的に低い優先度に調整されます。デフォルトでは、 analyzeの優先度は低くなっています。

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

トリガー戦略: auto analyzeは、新しいテーブルの行数が1000に達し、このテーブルに1分以内に書き込み操作がない場合に自動的にトリガーされます。

変更された数または現在の合計行数がtidb_auto_analyze_ratioより大きい場合、 analyzeステートメントが自動的にトリガーされます。デフォルト値のtidb_auto_analyze_ratioは0.5で、この機能がデフォルトで有効になっていることを示します。安全性を確保するために、機能が有効になっているときの最小値は0.3であり、デフォルト値が0.8であるpseudo-estimate-ratioより小さくする必要があります。そうでない場合、疑似統計が一定期間使用されます。 tidb_auto_analyze_ratioを0.5に設定することをお勧めします。

自動分析は、システム変数tidb_enable_auto_analyzeを使用して無効にできます。

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

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

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

Information schema is changedというエラーが報告されるのはなぜですか?

TiDBは、 schema回を使用してSQLステートメントを処理し、オンライン非同期DDL変更をサポートします。 DMLステートメントとDDLステートメントは同時に実行される可能性があり、各ステートメントが同じschemaを使用して実行されることを確認する必要があります。したがって、DML操作が進行中のDDL操作と一致すると、 Information schema is changedエラーが報告される場合があります。 DML操作中のエラー報告が多すぎるのを防ぐために、いくつかの改善が行われました。

現在、このエラー報告にはまだいくつかの理由があります(最初の1つだけがテーブルに関連しています):

  • DML操作に関係するいくつかのテーブルは、進行中のDDL操作に関係するテーブルと同じです。
  • DML操作は長時間続きます。この期間中に、多くのDDLステートメントが実行されたため、1024を超えるschemaバージョンの変更が発生します。 tidb_max_delta_schema_count変数を変更することにより、このデフォルト値を変更できます。
  • DML要求を受け入れるTiDBサーバーは、 schema informationを長時間ロードできません(TiDBとPDまたはTiKV間の接続障害が原因である可能性があります)。この期間中に、多くのDDLステートメントが実行されたため、100を超えるschemaバージョンの変更が発生しました。
  • TiDBの再起動後、最初のDDL操作が実行される前に、DML操作が実行され、最初のDDL操作が発生します(つまり、最初のDDL操作が実行される前に、DMLに対応するトランザクションが開始されます。最初のschemaバージョンの後DDLが変更され、DMLに対応するトランザクションがコミットされた場合、このDML操作はこのエラーを報告します。

ノート:

  • 現在、TiDBはschemaのバージョンの変更をすべてキャッシュしているわけではありません。
  • DDL操作ごとに、 schemaのバージョン変更の数は、対応するschema stateのバージョン変更の数と同じです。
  • DDL操作が異なると、 schemaバージョンの変更の数も異なります。たとえば、 CREATE TABLEステートメントは1つのschemaバージョン変更を引き起こし、 ADD COLUMNステートメントは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未満に保つことをお勧めします。それ以外の場合は、失敗したステートメントをクライアントから再試行する必要があります。

SQLの最適化

TiDB実行プランの説明

クエリ実行プランを理解するを参照してください。

統計収集

統計入門を参照してください。

select count(1)を最適化する方法は?

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

推奨事項:

  1. ハードウェア構成を改善します。 ソフトウェアとハードウェアの要件を参照してください。
  2. 並行性を改善します。デフォルト値は10です。50に改善して試してみることができます。ただし、通常、改善はデフォルト値の2〜4倍です。
  3. 大量のデータの場合はcountをテストします。
  4. TiKV構成を最適化します。 TiKVスレッドのパフォーマンスを調整するTiKVメモリパフォーマンスの調整を参照してください。
  5. コプロセッサーキャッシュを有効にします。

現在の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 job queries 'job_id' [, 'job_id'] ...job_idに対応するDDLタスクの元のSQLステートメントを表示します。 job_idは実行中のDDLジョブのみを検索し、最後の10件はDDL履歴ジョブキューになります。

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

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

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

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

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

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

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

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

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

通常、 root taskの入力データはcop taskから取得されます。 root taskがデータを処理する場合、 cop taskのTiKVが同時にデータを処理し、 root taskのTiDBがプルされるのを待ちます。したがって、 cop個のタスクが同時に実行されたと見なすことができます。しかし、それらのデータにはアップストリームとダウンストリームの関係があります。実行プロセス中、それらはしばらくの間同時に実行されます。たとえば、最初のcop task[100、200]のデータを処理し、次のcop task[1、100]のデータを処理しています。詳細については、 TiDBクエリプランを理解するを参照してください。

データベースの最適化

TiDBオプションの編集

TiDBコマンドオプションを参照してください。

ホットスポットを分散させる方法は?

TiDBでは、データは管理のためにリージョンに分割されます。一般に、TiDBホットスポットとは、リージョン内の読み取り/書き込みホットスポットを意味します。 TiDBでは、主キー(PK)が整数ではないテーブル、またはPKがないテーブルの場合、リージョンのホットスポットを分散するようにSHARD_ROW_ID_BITSを構成することで、リージョンを適切に分割できます。詳細については、 SHARD_ROW_ID_BITSの紹介を参照してSHARD_ROW_ID_BITS

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

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

このページの内容