วัน: 16 ตุลาคม 2019

SQL Server:audit inconsistent columns detectorSQL Server:audit inconsistent columns detector

ในโลกของการพัฒนาซอฟต์แวร์ขนาดใหญ่ (Enterprise Applications) ฐานข้อมูลเป็นหัวใจสำคัญที่เก็บข้อมูลทางธุรกิจทั้งหมด อย่างไรก็ตาม เมื่อระบบมีการขยายตัวหรือมีการเปลี่ยนแปลงโครงสร้าง (Schema Changes) บ่อยครั้ง อาจเกิดปัญหาที่เรียกว่า Schema Drift ซึ่งหมายถึงการที่คอลัมน์ที่มีชื่อความหมายเดียวกัน (เช่น `created_at`) แต่ถูกกำหนดคุณสมบัติทางเทคนิค (Data Type, Size, Nullability) แตกต่างกันในตารางที่ต่างกัน

ความไม่สอดคล้องเหล่านี้อาจไม่แสดงข้อผิดพลาดทันที แต่เมื่อถึงเวลาที่โค้ดพยายามอ่านหรือเขียนข้อมูลตามสมมติฐานที่ผิดพลาด จะนำไปสู่ข้อผิดพลาดร้ายแรง (Runtime Errors) หรือที่แย่กว่านั้นคือการเกิดข้อมูลที่ผิดพลาด (Data Corruption) โดยที่ผู้ใช้งานไม่ทราบสาเหตุ

💡 Schema Drift คืออะไร และทำไมต้องตรวจจับ?

Schema Drift คือการที่โครงสร้างของข้อมูล (Schema) ไม่เป็นไปตามมาตรฐานที่กำหนดไว้ในทุกตารางที่ควรจะใช้คอลัมน์นั้นๆ การตรวจจับความไม่สอดคล้องของคอลัมน์ (Inconsistent Columns Detector) จึงเป็นกระบวนการ Audit ที่สำคัญอย่างยิ่งสำหรับ Senior Architect เพื่อให้มั่นใจว่าข้อมูลที่ถูกดึงออกมาจากหลายแหล่งสามารถนำมาประมวลผลร่วมกันได้อย่างถูกต้อง

บทความนี้จะนำเสนอสคริปต์ PostgreSQL ที่ทรงพลัง ซึ่งออกแบบมาเพื่อสแกน metadata ของฐานข้อมูลทั้งหมด เพื่อค้นหาคอลัมน์ที่มีชื่อเชิงตรรกะ (Logical Name) เดียวกัน แต่มีคุณสมบัติทางกายภาพ (Physical Properties) ที่ขัดแย้งกัน

🛠️ PostgreSQL Script: Inconsistent Column Detector

สคริปต์นี้จะใช้ Common Table Expressions (CTEs) เพื่อทำความสะอาดและจัดระเบียบข้อมูลเมตา (Metadata) ก่อนที่จะเปรียบเทียบความแตกต่างในระดับคอลัมน์:

SQL

WITH RawColumns AS ( -- 1. ดึงข้อมูลดิบและทำความสะอาดชื่อคอลัมน์ SELECT table_schema AS SchemaName, table_name AS TableName, column_name AS ColumnName, LOWER(TRIM(column_name)) AS CleanedColumnName, data_type AS DataType, character_maximum_length AS CharLength, is_nullable AS IsNullable FROM information_schema.columns WHERE column_name IS NOT NULL), DiffCheck AS ( -- 2. ตรวจสอบความแตกต่างของคุณสมบัติ SELECT CleanedColumnName, COUNT(DISTINCT DataType) AS DistinctTypes, COUNT(DISTINCT CAST(CharLength AS TEXT)) AS DistinctSizes, COUNT(DISTINCT IsNullable) AS DistinctNullability FROM RawColumns GROUP BY CleanedColumnName HAVING COUNT(DISTINCT DataType) > 1 OR COUNT(DISTINCT CAST(CharLength AS TEXT)) > 1 OR COUNT(DISTINCT IsNullable) > 1) -- 3. แสดงผลลัพธ์ที่พบความขัดแย้ง SELECT DISTINCT r.SchemaName, r.TableName, r.ColumnName, r.CleanedColumnName, r.DataType, r.CharLength, r.IsNullable FROM RawColumns r INNER JOIN DiffCheck d ON r.CleanedColumnName = d.CleanedColumnName ORDER BY r.CleanedColumnName, r.SchemaName, r.TableName;

⚙️ หลักการทำงานของสคริปต์

  1. RawColumns CTE: ทำหน้าที่รวบรวมข้อมูลเมตาของคอลัมน์ทั้งหมดจาก `information_schema.columns` และที่สำคัญที่สุดคือการสร้าง `CleanedColumnName` เพื่อให้สามารถเปรียบเทียบชื่อคอลัมน์ที่อาจมี Prefix ต่างกัน (เช่น `user_id` และ `tbl_user_id` ถูกรวมเป็น `user_id`)
  2. DiffCheck CTE: ส่วนนี้คือหัวใจของการตรวจสอบ โดยการ Group By ตาม `CleanedColumnName` และใช้ `HAVING` clause เพื่อกรองเฉพาะกลุ่มคอลัมน์ที่มีค่าความแตกต่าง (Distinct Count) ของ Data Type, Size, หรือ Nullability มากกว่า 1
  3. Final Select: นำผลลัพธ์จาก `DiffCheck` มา Join กลับกับ `RawColumns` เพื่อดึงรายละเอียดทั้งหมดของคอลัมน์ที่ถูกระบุว่ามีความไม่สอดคล้องกันออกมาให้ผู้ใช้งานตรวจสอบ

✅ บทสรุปและการนำไปใช้

การใช้ Detector นี้ช่วยลดความเสี่ยงของ Schema Drift ได้อย่างมาก ทำให้ทีมพัฒนาสามารถมั่นใจได้ว่าข้อมูลที่ถูกดึงมาใช้ใน Report, ETL Pipeline, หรือ Microservices ต่างๆ มีโครงสร้างที่สม่ำเสมอและเชื่อถือได้

ในฐานะ Senior Architect ควรนำสคริปต์นี้ไปรันเป็นส่วนหนึ่งของ CI/CD Pipeline หรือเป็นงานตรวจสอบประจำสัปดาห์ เพื่อให้การดูแลความสมบูรณ์ของโครงสร้างฐานข้อมูลเป็นไปอย่างอัตโนมัติและต่อเนื่อง