Litmus — 話題のニュースを、深く読み解く。 RSS
ソフトウェア

PowerShell 7.7のNew-Guid、既定で時系列に並ぶGUIDを作る

2026年11月10日公開のPowerShell 7.7で、New-Guidの既定がUUID v7に変わった。作成時刻を埋め込み、データベースの主キーに向いた設計になった仕組みを解説する。

ぼかしの効いた、カラフルなプログラムコードが表示されたディスプレイのクローズアップ

イメージ写真 記事の内容を撮影したものではありません。Photo by Markus Spiske on Pexels

この記事には Amazon アソシエイトのリンクを含みます。

PowerShellでNew-Guidを実行すると、d3e4f5a6-1234-4abc-9def-abcdef012345のような一意な値が返ってくる。スクリプトでファイルの名前やレコードのIDを作るとき、多くの人は「他と被らなければいい」という理由だけでこのコマンドレットを使っている。2026年11月10日に公開されたPowerShell 7.7で、このNew-Guidが返す値の作られ方が変わった。

見た目の桁数は同じでも、値の中身は別物になっている。何が変わり、何がうれしいのかを、ビットの中身から追った。

New-Guidの既定がv7に変わった

PowerShell公式の「What’s New in PowerShell 7.7」は、破壊的変更の一覧にこう書いている。「New-Guidは、既定でバージョン4(ランダム)ではなくバージョン7(時系列に並べ替え可能)のUUIDを生成するようになった。出力の書式は変わらない。完全にランダムなGUIDに依存するスクリプトは、[guid]::NewGuid()を直接呼び出す必要がある」。

変更元はGitHubのプルリクエスト#27033で、2026年6月26日にPowerShell本体のリポジトリへ取り込まれた。8-4-4-4-12という区切り方は今までと変わらないため、画面に出た値を一目見ただけでは気づきにくい。変わったのは、その値がどう組み立てられるかという内側の仕組みだ。

実装としては、New-Guidが内部で呼ぶメソッドが変わった。.NET公式リファレンスによると、Guid.CreateVersion7()は「RFC 9562に従い、バージョン7の書式でGuidを新しく作る」メソッドだ。.NET 9から用意されている。PowerShell 7.7は、この.NET側の機能をコマンドレットの既定に昇格させた形になる。

この変更が及ぶのは、クロスプラットフォーム版のPowerShell 7.x系になる。Windowsに長年付属してきたWindows PowerShell 5.1は、7.xとは別の古い基盤で動いており、今回の更新の対象外だ。使っているのがどちらかは、$PSVersionTableを実行すれば確認できる。

UUIDにはバージョンという区分があり、今回その既定が4から7へ動いた。バージョン4は中身のほとんどを乱数で埋める作り方で、PowerShellは7.6までこれを使ってきた。バージョン7は、先頭に作成時刻を埋め込む作り方になる。バージョン名が変わったと分かっても、128ビットのうち何が足され、何が変わったのかまではまだ見えてこない。

v4とv7はビット構造が違う

GUID(UUID)は128ビットの値だ。IETFのRFC 9562が定める書式に沿って作られる。バージョン4は、バージョンとバリアントを示す決まったビットを除いた122ビットすべてを乱数で埋め、時刻の情報は一切含まない。

バージョン7は、この128ビットの使い道を作り直している。

020406080100120UUID v7の128ビット タイムスタンプUUID v7の128ビット 乱数BUUID v7の128ビット 版UUID v7の128ビット 乱数AUUID v7の128ビット バリアントタイムスタンプ版乱数Aバリアント乱数BUUID v7の128ビットUUID v7、128ビットの内訳出典: RFC 9562 5.7節

図のとおり、先頭48ビットが1970年1月1日からのミリ秒数(タイムスタンプ)で埋まり、全体の3分の1強を占める。残りは、バージョンとバリアントを示す6ビットと、74ビット(12+62)の乱数に分かれる。乱数に使えるビット数はバージョン4の122ビットより減るが、並び順を手に入れる代わりにこの配分を選んだのがバージョン7の設計になる。ビットの使い道が変わったことは分かった。では、先頭に時刻を置くと、具体的に何が良くなるのか。

時刻順だと索引への書き込みがまとまる

自分も最初は、GUIDはただの乱数の塊で、並び順に意味はないと思っていた。RFCを読んで、その理解が変わった。

多くのデータベースは、値を順番に並べた索引(インデックス)を使って、目的のレコードを素早く探せるようにしている。索引は、新しい値が入ってくるたびに、その値がふさわしい位置へ割り込ませる必要がある。

GUIDがバージョン4(完全ランダム)だと、新しい値は索引のあちこちにランダムな位置で割り込む。RFC 9562の2.1節は、この挿入のされ方が索引への書き込み性能を大きく落とすと述べている。

性能差は、1桁以上にもなるという。

GUIDがバージョン7なら、新しく作った値ほど先頭のタイムスタンプが大きくなる。たとえば今日作ったGUIDと明日作ったGUIDを比べると、文字列として並べ替えるだけで明日の分が後ろに来る。本棚の一番手前に新刊を積み足すように、索引の中で新しい値は常に末尾付近にまとまって入っていく。RFC 9562の6.11節は、この性質によって関連するデータを索引の近い位置にまとめられ、性能が上がると説明している。新しいGUIDほど値が大きくなるという単純な性質が、索引への書き込みをまとめる効果を生んでいる。

ランダム性が要る処理は影響を受ける

ここまでの変更は、データベースを設計する人には朗報だ。一方で、New-Guidを別の目的で使っているスクリプトには注意が要る。

公式の破壊的変更の一覧は、「完全にランダムなGUIDに依存するスクリプトは、[guid]::NewGuid()を直接呼び出す必要がある」と案内している。文字列の書式(8-4-4-4-12の並び)は変わらないため、生成された値を見た目だけで判別する処理は影響を受けない。影響を受けるのは、値の予測しにくさそのものを前提にしたコードだ。

RFC 9562の8節も、埋め込まれたタイムスタンプ自体は攻撃の手がかりとしては小さいとしている。ただし作成された順序が分かってしまう点を挙げ、セキュリティ用途のUUIDにはバージョン4を使うべきだとしている。トークンや、推測されたくない識別子をNew-Guidで作っていた場合は、ここが当てはまる。GUIDの作り方以外にも、7.7では何が変わったのか。

ほかの変更点も見ておく

New-Guidの変更は、PowerShell 7.7全体のうちの1つにすぎない。公式の「What’s New」ページは、ほかにも次を挙げている。

  • 一時ディレクトリを1コマンドで作れるNew-TemporaryDirectoryコマンドレットの追加
  • Join-Pathへの-Extensionパラメーターの追加
  • Format-Tableなどの-Propertyに空値を渡したときに送出される例外の種類の変更
  • 制約付き言語モードでの、コア以外のオブジェクトへのプロパティ代入の制限強化
  • リモート処理での引数・フレームの検証強化

土台も変わった。7.7は.NET 11をベースにしている。変更点は多いが、スクリプトを書くときにまず意識しておきたいのは、New-Guidの既定が変わったという1点になる。

まとめ

PowerShell 7.7で、New-Guidの既定はバージョン4(完全ランダム)からバージョン7(先頭48ビットが作成時刻)に変わった。文字列の書式は変わらないが、中身の作り方が変わったことで、作った順に並べられるGUIDを既定で手に入れられるようになった。

データベースの主キーなど、値の並び順が性能に関わる場面では、この変更がそのまま効いてくる。一方で、完全なランダム性を前提にしたスクリプトでは[guid]::NewGuid()への置き換えが要る。使い慣れたNew-Guidの中身が変わったことに、まず気づいておきたい。

この記事の先を読む本を探す

特定の本を勧めるものではありません。検索結果から、いまの版と目次を確かめて選んでください。

コメント

気づきや感想をどうぞ

記事への補足や、読んで考えたことをお寄せください。個人情報や、他の人を傷つける内容の投稿はお控えください。

コメントを読み込んでいます…

    ほかの記事

    最新の記事 →