このページはCalíope 1.7を紹介しています。私がいま作っているバージョンです。1.6は、Mac、iPad、iPhone、Apple Watch、Apple TV、Apple Vision Pro向けにApp Storeで公開中です。それぞれの機能がどのバージョンで入ったかは変更履歴に書いてあります。

すべてのトピックに「Calíopeで開く」ボタンを追加します。アプリがインストールされている場合にのみ機能します。

一括検索

検索にかかるコスト

列の中のテキスト検索ではインデックスを使えません。すべての行が読まれるため、Calíopeは開始前にその量を伝えます。

列の中にあるテキストの検索には、どのインデックスも活用できません。これはCalíopeの制限ではなく、リレーショナルデータベースの仕組みです。インデックスが並べられるのは値の先頭であって、値の途中にあるものではありません。

そのため、検索のたびに、選択した各テーブルのすべての行が読まれます。開始する前に、スキャンするテーブルの数とその容量を示す通知が表示されるのはそのためです。

速くする方法

- すべてではなく、検索する意味のあるテーブルだけを選択します。
- まず小さなテーブルでテキストが正しいことを確かめてから、範囲を広げます。
- サーバがSSHトンネルの向こうにある場合は、レイテンシの影響が出ることを見込んでください。

表示される容量はサーバのカタログから取得したものなので、推定値です。更新の多いテーブルでは、実際より少なかったり多かったりすることがあります。

キーワード: コスト、遅い、インデックス、パフォーマンス、サイズ、スキャン、大きなテーブル

見つかった行が置換された行より多い理由

検索はサーバの規則に従って大文字と小文字を区別しませんが、置換は区別します。Calíopeはその差を正確な数で示します。

これはこのツールでいちばん重要な落とし穴です。だからこそCalíopeは、隠さずに表示します。

検索と置換では比較のしかたが違います。検索はふつう大文字と小文字を区別しません。fooを検索するとFooやFOOも見つかります。一方、置換は常に区別し、変更するのはfooだけです。

MySQLMariaDBAuroraTiDB

検索を決めるのは列の*照合順序*で、ほとんどのデータベースでは大文字と小文字を区別しません。書き込みに使うREPLACE()はバイト単位で比較します。

TiDB

独自の照合順序を指定せずに作成したTiDBのデータベースは、サーバの照合順序utf8mb4_binを使います。これは大文字と小文字を区別するので、そこでは検索と置換の結果が一致します。

SQL Server

検索は列の*照合順序*に従い、ふつうは大文字と小文字を区別しません。REPLACE()もそれに従うので、Calíopeは同じ照合順序のうち大文字と小文字、アクセントを区別するものを使って比較させます。警告が数えるのは、その書き込みで変わるものです。

PostgreSQL

検索にはILIKEを使い、照合順序に関係なく大文字と小文字を区別しません。書き込みに使うreplace()は文字単位で比較します。

Oracle

Oracleでは、LIKEもREPLACE()も大文字と小文字を区別します。「大文字と小文字を区別」がオフのとき、検索は両方のテキストを大文字(UPPER())にして比較するのでFooやFOOも見つかり、警告は大文字と小文字を区別するREPLACE()で変わるものを数えます。

誰もこれを指摘しなければ、300行と告げて100行しか変えない置換になります。何も失敗せず、エラーメッセージも出ません。データは半分だけ移行された状態になります。

Calíopeがすること

- 同じクエリーで2つの数を別々に数え、それぞれを示す警告を表示します。
- 各列の合計の横に、実際に置換できる行数が表示されます。
- プレビューには、実際に変わる行だけが表示されます。

あなたにできること

- 検索するときに「大文字と小文字を区別」をオンにします。そうすれば、見つかったものがそのまま置換されるものになり、警告は消えます。
- または、表記ごとに(foo、Foo、FOO)複数回に分けて行います。

キーワード: 大文字と小文字、大文字、小文字、照合順序、不一致、警告、差分、区別

置換できる列

すべてのテキスト列が検索の対象ですが、書き込めない列もあります。Calíopeはどの列か、その理由も示します。

検索はすべてのテキスト列が対象です。短いテキストと長いテキスト、固定リスト、JSONドキュメントです。

置換は4つの場合には提供されず、どの場合も列に鍵アイコンとその理由が表示されます。

理由なぜか
サーバが計算する列値はほかの列から決まるので、書き込んでも効果がありません
固定リストの値しか受け付けない置換でリスト外の値になることがあり、サーバによっては警告なしに空のテキストに変えてしまいます
主キーの一部変更するとほかのテーブルとの関係が壊れることがあります
一意インデックスがある新しい値がすでにある値と衝突することがあります

SQL Server

SQL Serverには固定リストに限られる列がないので、ここでは3つの場合になります。xml列は置換の対象で、置換後も有効なXMLである必要があります。XMLを壊す書き込みはサーバが拒否します。

PostgreSQL

PostgreSQLでは、固定リストはENUM型です。json列とjsonb列は置換の対象で、置換後も有効なJSONである必要があります。JSONを壊す書き込みはサーバが拒否します。

Oracle

Oracleには値が固定リストに限られる列がないので、ここでは3つの場合になります。CLOB列とNCLOB列は短いテキストと同じように検索・置換されます。LONG、XMLTYPE、JSONの列は検索されません。

主キーのないテーブルは置換されません。このことは確認ウインドウに示されます。キーがなければ各行を特定する方法がなく、一致の範囲が広すぎる書き込みは、誰も見ていないレコードに手を付けてしまいます。

ビューは対象外です。書き込みを受け付けるビューもありますが、どれがそうかを判断するには定義を解析する必要があり、そのリスクに見合いません。

キーワード: 列、生成列、計算列、ENUM、主キー、一意、JSON、鍵アイコン、ブロック

驚きのない置換

置換は必ずサーバが計算したプレビューを経由します。実行せずにSQLをエディタへ持っていくこともできます。

一括置換は、1行ずつ見ていないデータに対するまとめての書き込みです。そのため、確認ウインドウを経ずに実行することはできません。

何かが書き込まれる前に表示されるもの

1. どのテーブルとどの列に手を付けるか、それぞれ何行か。
2. 行ごとの変更前 → 変更後のプレビュー。
3. 当てはまる警告。見つかったものと置換できるものの差、ブロックされた列、変更しようとしているものに依存する外部キー。

プレビューはサーバが計算します。書き込みを行うのと同じ操作を使います。Calíopeのシミュレーションではありません。表示されるのは、文字どおり保存される内容です。そうでなければずっと後になって気づく、最大長による切り詰めも含まれます。

「スクリプトを表示」は、自分でコピーして実行したり保存したりするための完全なSQLを表示します。このボタンは何も書き込みません。

さらに2つの歯止め

- 1,000行を超える場合は、確定するために行数を入力する必要があります。
- 各テーブルはそれぞれのトランザクションの中で書き込まれ、その後、変更された行数が告げられた行数と照合されます。一致しなければそのことが伝えられます。終わると、検索フィールドの下の1行に置換された行数が表示され、数が足りない場合は、足りなかったテーブルが示されます。

取り消しはできません。大事なデータに手を付けるなら、先に「バックアップ」ツールでバックアップを取ってください。

ClickHouse

ClickHouseでは、置換はミューテーションです。キューに入り、サーバがバックグラウンドで適用するので、トランザクションも変更された行数もありません。1行の表示は、いくつのテーブルでキューに入ったかを示し、その進行は「プロセス」ツールで追えます。終わったらもう一度検索してください。キーの列、FixedString、Enumは検索されますが書き込まれず、ORDER BYのないテーブルは置換の対象として提供されません。

読み出し専用の環境タグがある場合、置換は表示されません。検索は引き続き使えます。書き込みの確認を求めるタグなら、置換は書き込む前に一度だけ確認します。

キーワード: 置換、プレビュー、確認、スクリプト、SQL、トランザクション、取り消し、バックアップ