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ステートメント。これは、単一の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} \ --batch1つのTiDBトランザクションで制限された数のステートメントを増やすこともできますが、これにより多くのメモリが消費されます。
TiDBにはOracleのフラッシュバッククエリのような機能がありますか? DDLをサポートしていますか?
はい、そうです。また、DDLもサポートしています。詳細については、 TiDBが履歴バージョンからデータを読み取る方法を参照してください。
TiDBはデータを削除した直後にスペースを解放しますか?
DELETE
、およびTRUNCATE
の操作のいずれも、データをすぐに解放しませDROP
。 TRUNCATE
およびDROP
の操作では、TiDB GC(ガベージコレクション)時間(デフォルトでは10分)の後、データが削除され、スペースが解放されます。 DELETE
回の操作では、データは削除されますが、圧縮が実行されるまでスペースはすぐには解放されません。
TiDBはREPLACE INTO
構文をサポートしていますか?
はい。例外は、 LOAD DATA
が現在REPLACE INTO
構文をサポートしていないことです。
データが削除された後、クエリ速度が遅くなるのはなぜですか?
大量のデータを削除すると、多くの役に立たないキーが残り、クエリの効率に影響します。現在、この問題を解決することが期待されるリージョンマージつの機能が開発中です。詳細については、 TiDBベストプラクティスのデータセクションの削除を参照してください。
データを削除した後にストレージスペースを再利用するのが遅い場合はどうすればよいですか?
TiDBはマルチバージョン同時実行制御(MVCC)を使用するため、データを削除してもすぐにスペースが再利用されるわけではありません。ガベージコレクションは、同時トランザクションが以前のバージョンの行を表示できるように遅延されます。これは、 tidb_gc_life_time
(デフォルト: 10m0s
)システム変数を介して構成できます。
SHOW PROCESSLIST
はシステムプロセスIDを表示しますか?
TiDB1の表示内容はSHOW PROCESSLIST
とほぼ同じSHOW PROCESSLIST
。 show processlist
はシステムプロセスIDを表示しません。表示されるIDは、現在のセッションIDです。 show processlist
とshow 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と組み合わせて使用できます。例えば:
データベースに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;全表スキャンステートメントは、自動的に低い優先度に調整されます。デフォルトでは、
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は、 ヒントと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はネットワークアクセスを実行する必要があります。
推奨事項:
- ハードウェア構成を改善します。 ソフトウェアとハードウェアの要件を参照してください。
- 並行性を改善します。デフォルト値は10です。50に改善して試してみることができます。ただし、通常、改善はデフォルト値の2〜4倍です。
- 大量のデータの場合は
count
をテストします。 - TiKV構成を最適化します。 TiKVスレッドのパフォーマンスを調整するとTiKVメモリパフォーマンスの調整を参照してください。
- コプロセッサーキャッシュを有効にします。
現在の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 task
とroot 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メモリパフォーマンスの調整を参照してください。