クイズ:Postgres深掘り 第2部
あなたはSQLの鉄人か?それとも、ただのSQL初心者か?
Part 2 of 2. パート1に戻る
PostgreSQL深掘りクイズのパート2へようこそ!
このクイズでは、JOIN、NULL、ANSI SQL、トランザクション、内部構造、インデックス、データサンプリングなど、PostgreSQLの定番機能から意外と知られていない落とし穴まで幅広くカバーしています。
健闘を祈ります! 🍀
PostgreSQLの有効なJOIN式ではない ❌ ものはどれ?
CROSS JOIN は知っていたかな?
JOIN ALL を見て、別の操作である UNION ALL を連想しなかっただろうか?
ここでの正解は JOIN ALL ❌ だ。
正しいJOINの種類は以下の通り:
INNER JOIN(デフォルトの JOIN)LEFT JOIN(またはLEFT OUTER JOIN)RIGHT JOIN(またはRIGHT OUTER JOIN)FULL JOIN(またはFULL OUTER JOIN)CROSS JOIN(デカルト積。ただし、後続のWHERE句でフィルタリングされない限り)
「サイドエフェクトに依存する」以外の場合、エラーが発生した後に何が起こるか?
BEGIN;UPDATE students SET status = 'alumni' WHERE grade = 12;UPDATE students SET graduation_date = CURRENT_DATE WHERE grade = 12;UPDATE students SET grade = 'GRADUATED'; -- 🚨 Error: type mismatchCOMMIT;ここでエラーが発生した場合:
- トランザクション全体がロールバックされる
- 変更は一切コミットされない
- トランザクションは失敗としてマークされる
部分的にコミットするには:
BEGIN;UPDATE ...;SAVEPOINT my_save;UPDATE ...; -- ErrorROLLBACK TO my_save;COMMIT;PostgreSQLにおいて、HASH JOINを使用できるのはどのON条件ですか?
SELECT *FROM students aJOIN grades bON /* What goes here? ⁉ */;ハッシュ結合(hash join)は、ON句に等価条件(=)がある場合に実行可能です。
=はハッシュ結合における主要な述語の形式です>や>=はハッシュ結合の述語にはなりませんHASH JOINという構文はPostgreSQLでは無効です
なお、テーブルのサイズ、統計情報、インデックス、およびメモリ設定によっては、プランナがネステッドループ結合やマージ結合を選択する場合もあります。
大文字小文字を区別するカラム名には、どちらが正しいですか?
CREATE TABLE grades ( "Student Name" VARCHAR(100), 'Student Grade' INTEGER);PostgreSQLにおいて:
- ダブルクォート (
") は識別子(テーブル名、カラム名)に使用します - シングルクォート (
') は文字列リテラルに使用します
ベストプラクティス:
- 名前の中で大文字小文字を混ぜたり、スペースを使用したりするのは避けましょう
- 識別子には snake_case を使用しましょう
- 引用符付きの識別子は、どうしても必要な場合にのみ使用しましょう
ピリオドを含むカラム名を指定するにはどうすればよいでしょうか?
CREATE TABLE teachers ( id INT GENERATED BY DEFAULT AS IDENTITY, first.name TEXT, -- How do you include the column: first.name? salary NUMERIC);PostgreSQLでは、識別子のクォーティングに二重引用符(ダブルクォート)を使用します:
- 識別子(カラム名、テーブル名)には二重引用符
"..."を使用 - 文字列リテラルには単一引用符(シングルクォート)
'...'を使用 first.nameという形式は、通常table_name.column_nameと解釈されます
クォートがない場合、カラム名に含まれるピリオドはスキーマやテーブルの区切り文字として解釈されてしまいます!さらに、クォートされていない識別子はデフォルトで小文字に変換されます。
予期せぬトラブルを避けるため、識別子には snake_case を使用し、特殊文字の使用は控えるのが最善です。
学生の 10% をランダムにサンプリング するための有効な構文はどれですか?
これはかなり意地悪な問題です!約6つの罠が仕掛けられています。例えば:
- 高レベルな説明と構文の断片。不完全な情報をいかに適応させ、組み立てるかをテストしています。
TABLESAMPLEの構文に関する正確な知識が必要です。提示されたTABLESAMPLEの選択肢の中に正しい構文は一つもありません!(邪悪でしょう?わかっています!でも諦めないで、あなたならできるはず!!! ❤️)ROW_NUMBER() OVER (ORDER BY RAND())とORDER BY RANDOM() > 10はさらなる「赤にしん(おとり)」です。正解っぽく見えますが、違います。そもそもRAND()という関数は存在しません。また、RANDOM()は常に0.0から1.0の範囲の値を返すため、RANDOM() > 10というブール式は常に偽になります。 もう一つの問題として、ORDER BY RANDOM() > 10はランダムな数値ではなくブール値でソートしてしまいます。しかし、この> 10という数字は、いかにもパーセンテージっぽく見えましたよね?BERNOULLIは有効ですが、SAMPLETABLEは無効です。WHERE RANDOM() >= 0.1はひっかけです!RANDOM()は0.0 <= x < 1.0の範囲の値を返すため、>= 0.1とすると行の約 90% が返されてしまい、10% にはなりません。
TABLESAMPLE メソッドに関して、PostgreSQL は以下の2つのサンプリング方式をサポートしています:
BERNOULLI: 各行が等しい確率を持つSYSTEM: ブロックレベルのサンプリング(高速だがランダム性は低い)
サンプリングについて詳しく知りたい場合は、Render のこの記事をチェックしてください。
例:
-- Sample 10% of rowsSELECT * FROM students TABLESAMPLE BERNOULLI (10);
-- For repeatable results, use REPEATABLE:SELECT * FROM studentsTABLESAMPLE BERNOULLI (10) REPEATABLE (42);また、TABLESAMPLE はあまりランダムではないという報告もあります。もし、より精度の高いランダムな固定サイズのサンプルが必要な場合は、ORDER BY RANDOM() LIMIT 10 の使用を検討してください。ただし、これは 10% ではなく「10行」を返すこと、そして巨大なテーブルでは低速になる可能性があることに注意してください。
より優れたランダムサンプリング手法を提供するサードパーティ製の拡張機能もありますが、それは今回の範囲外です! 😅
この呪文は何を実行するもの?
CREATE INDEX idx_active_studentsON students(last_name)WHERE status = 'active';このテクニックは Partial Index(部分インデックス)と呼ばれる。
通常、行の特定のサブセットのみがクエリの対象となる場合に、ディスク使用量を削減し、クエリを高速化するのに役立つ。
プランナが、クエリの条件から status = 'active' が成り立つと証明できる場合に、このインデックスを候補にできます。完全な文字列一致は必須ではありませんが、推論には限界があり、パラメータ化された条件では計画時に証明できない場合があります。候補になっても、実際に選択されるとは限りません。
注意: Postgresは他のRDBMSのような「クエリヒント」をサポートしていない。クエリプランナが、適切なインデックスを使用するかどうかを自律的に判断する。
UPDATE 文に対して EXPLAIN ANALYZE を実行するとどうなりますか?
EXPLAIN ANALYZEUPDATE studentsSET grade = grade + 1WHERE status = 'active';EXPLAIN ANALYZE は実際にクエリを実行します!書き込み操作、特に UPDATE、DELETE、INSERT 文を分析する際は注意が必要です。再現性のある結果を得るために、EXPLAIN ANALYZE を実行するたびにクリーンアップ操作が必要になる場合があります。
ベストプラクティス:
UPDATE/DELETE/INSERTには(ANALYZE なしの)EXPLAINを使用する- 変更操作をトランザクションで囲む:
BEGIN;EXPLAIN ANALYZE ...;ROLLBACK;お見事!PostgreSQLの様々な領域を深く掘り下げましたね。🐘
何か新しい学びがあったか、少なくとも自慢できるようなスコアが得られたなら幸いです!🏆
さらなる刺激を求めていますか?クイズコレクションで、終わりのない*楽しみを!
