ป้ายกำกับ: Time

SQL Server: ปรับ column date, time ให้เร็วขึ้นSQL Server: ปรับ column date, time ให้เร็วขึ้น

อันนี้เป็น script ที่ปรับใหม่ให้ column date, time ต่าง ๆ ทำงานงานได้เร็วขึ้น มีประสิทธิ์ภาพมากขึ้นโดย ยังให้ทาง SA ได้เลือกเองอยู่ว่าจะ alter ใหม่มั๋ย หรือจะใช้โครงสร้างเดิม
alter_table_optimize_by_storage_bytes_columns_types_date_and_ time.sql

/*
https://learn.microsoft.com/en-us/sql/t-sql/data-types/time-transact-sql?view=sql-server-ver16#table-structure

Reference Storage Size:
1. DATETIME2 & TIME: https://learn.microsoft.com/en-us/sql/t-sql/data-types/datetime2-transact-sql?view=sql-server-ver16#table-structure
 - Precision 0-2: 6 bytes
 - Precision 3-4: 7 bytes
 - Precision 5-7: 8 bytes
2. DATETIME (Legacy):
 - Fixed 8 bytes (Less precision than datetime2)
3. DECIMAL/NUMERIC:
 - Precision 1-9: 5 bytes
 - Precision 10-19: 9 bytes
 - Precision 20-28: 13 bytes
 - Precision 29-38: 17 bytes
*/

WITH StorageCalc AS (
 SELECT
  table_catalog,
  table_schema,
  table_name,
  column_name,
  DATA_TYPE,
  COALESCE(NUMERIC_PRECISION, DATETIME_PRECISION) AS CurrentPrecision,
  NUMERIC_SCALE AS CurrentScale,

  -- คำนวณขนาด Storage ปัจจุบัน (โดยประมาณ) เพื่อเปรียบเทียบ
  CASE
   WHEN DATA_TYPE = 'datetime' THEN 8
   WHEN DATA_TYPE IN ('datetime2', 'time') THEN
    CASE
     WHEN DATETIME_PRECISION <= 2 THEN 6
     WHEN DATETIME_PRECISION <= 4 THEN 7
     ELSE 8
    END
    -- (ละเว้นกลุ่ม Decimal ไว้คงเดิมสำหรับ logic นี้)
  END AS CurrentStorageBytes
 FROM
  information_schema.columns
 WHERE
  DATA_TYPE IN ('decimal', 'numeric', 'datetime', 'datetime2', 'time', 'datetimeoffset')
  AND table_schema NOT IN ('sys', 'information_schema') -- กรอง System tables ออก
),
OptimizationLogic AS (
 SELECT
  *,
  CASE
   -------------------------------------------------------
   -- 1. เปลี่ยน DATETIME (8 bytes) เป็น DATETIME2(3) (7 bytes)
   -- ประหยัดพื้นที่ได้จริง 1 Byte และแม่นยำกว่าเดิม
   -------------------------------------------------------
    WHEN DATA_TYPE = 'datetime' THEN 'datetime2'

   ELSE DATA_TYPE
  END AS SuggestedDataType,

  CASE
   -------------------------------------------------------
   -- กลุ่ม DECIMAL (เหมือนเดิม)
   -------------------------------------------------------
   WHEN DATA_TYPE IN ('decimal', 'numeric') THEN
    CASE
     WHEN CurrentPrecision BETWEEN 1 AND 9 THEN 9
     WHEN CurrentPrecision BETWEEN 10 AND 19 THEN 19
     WHEN CurrentPrecision BETWEEN 20 AND 28 THEN 28
     WHEN CurrentPrecision BETWEEN 29 AND 38 THEN 38
    END

   -------------------------------------------------------
   -- 2. กรณีเจอ DATETIME เดิม ให้แนะนำ Precision 2 (6 bytes)
   -- (ประหยัดกว่าเดิม 2 bytes และครอบคลุมวินาที)
   -------------------------------------------------------
   WHEN DATA_TYPE = 'datetime' THEN 2

   -------------------------------------------------------
   -- 3. ปรับ DATETIME2 / TIME / OFFSET ให้คุ้ม Storage Bucket
   -------------------------------------------------------
   WHEN DATA_TYPE IN ('datetime2', 'time', 'datetimeoffset') THEN
    CASE
     -- ใช้ 6 Bytes เท่ากัน -> เอาให้สุดที่ 2
     WHEN CurrentPrecision BETWEEN 0 AND 2 THEN 2
     -- ใช้ 7 Bytes เท่ากัน -> เอาให้สุดที่ 4
     WHEN CurrentPrecision BETWEEN 3 AND 4 THEN 4
     -- ใช้ 8 Bytes เท่ากัน -> เอาให้สุดที่ 7
     WHEN CurrentPrecision BETWEEN 5 AND 7 THEN 7
    END
  END AS SuggestedPrecision
 FROM StorageCalc
)
SELECT
 table_catalog AS DatabaseName,
 table_schema AS SchemaName,
 table_name AS TableName,
 column_name AS ColumnName,

 -- แสดงสถานะปัจจุบัน
 UPPER(DATA_TYPE) +
 CASE
  WHEN DATA_TYPE IN ('decimal', 'numeric') THEN '(' + CAST(CurrentPrecision AS VARCHAR) + ',' + CAST(CurrentScale AS VARCHAR) + ')'
  WHEN DATA_TYPE = 'datetime' THEN '' -- datetime ไม่มี precision ให้โชว์
  ELSE '(' + CAST(CurrentPrecision AS VARCHAR) + ')'
 END AS CurrentType,

 -- คำแนะนำใหม่
 UPPER(SuggestedDataType) +
 CASE
  WHEN SuggestedDataType IN ('decimal', 'numeric') THEN '(' + CAST(SuggestedPrecision AS VARCHAR) + ',' + CAST(CurrentScale AS VARCHAR) + ')'
  ELSE '(' + CAST(SuggestedPrecision AS VARCHAR) + ')'
 END AS SuggestedType,

 -- ไฮไลท์ว่าทำไมถึงแนะนำ
 CASE
  WHEN DATA_TYPE = 'datetime' THEN 'Save 1 Byte & Better Precision'
  WHEN SuggestedPrecision > CurrentPrecision THEN 'Maximize Precision for same Storage Size'
  ELSE 'Optimize Type'
 END AS OptimizationReason,

 -- Script ALTER
 'ALTER TABLE ' + Quotename(table_schema) + '.' + Quotename(table_name) +
 ' ALTER COLUMN ' + Quotename(column_name) + ' ' +
 UPPER(SuggestedDataType) +
 CASE
  WHEN SuggestedDataType IN ('decimal', 'numeric') THEN '(' + CAST(SuggestedPrecision AS VARCHAR) + ',' + CAST(CurrentScale AS VARCHAR) + ')'
  ELSE '(' + CAST(SuggestedPrecision AS VARCHAR) + ')'
 END + ';' AS AlterScript

FROM OptimizationLogic
WHERE
 -- กรองเฉพาะแถวที่ควรแก้ (Type เปลี่ยน หรือ Precision เปลี่ยน)
 (DATA_TYPE != SuggestedDataType)
 OR (CurrentPrecision != SuggestedPrecision)
ORDER BY
 DatabaseName, -- เรียงตาม Database
 SchemaName, -- เรียงตาม Schema
 TableName,  -- เรียงตาม Table
 ColumnName; -- เรียงตาม Column

อ่านเพิ่มเติม