Web Applications ส่วนใหญ่ใช้ Data Store บางประเภท มักเป็น Relational Database เมื่อ Web App สำเร็จ มันง่ายเกินไปที่จะเริ่ม "Hoarding" Data ใน Database แต Hoarding Data นำไปสู่ Unbounded Growth ของ Database Tables (ทั้ง Row Count และ Stored Data Size)
แม้ทำงานได้ดีถึงจุดหนึ่ง แตป้องกัน Data Bloat บางส่วน — หรือถ้าป้องกันไม่ได้ Plan Infrastructure ไว้ล่วงหน้า Manage Growth ให้เหมาะสม — เป็นเรื่อง Useful มาก
ก่อน Dive In มาดูว่าเราอาจจบลงกับ Bloated Applications ยังไง
More Data ไม่ได้หมายถึง Great เสมอไป
Applications ส่วนใหญ่ที่เราทำงาน Tend to Get Bigger ตามเวลา
ถ้าใช้ Cloud Provider สำหรับ Database คุณอาจ Hit Allocated Storage Limit เมื่อเกิดขึ้น ต้อง Upgrade Instance Type Heroku PostgreSQL Databases มี Limit เช่น Hobby Tier Limited 1GB Data
More Data มี Implications สำหรับ Query Speeds อะไรก่อนหน้านี้ Possible Without Index กลาย Impossible With Larger Tables Row Range Scans บางอย่าง Slower More Locks Acquired สำหรับ Database UPDATE และ DELETE Operations
How Database Tables Grow (ตารางเติบโตอย่างไร)
Data Hoarding เกิดขึ้น Gradually อะไร Not Problem Today กลาย Problem ในเดือนหนึ่งหรือ 6 เดือน สิ่ง Treacherous ที่สุดคือ Easy to Miss พิจารณา Classic Scenarios:
- Compliance Reasons Adopt Gem
paper_trailได้ Tableaudit_log_entriesทุก Operation ที่ Significant สร้าง Row ใน Table นั้น Audit Log Entries ไม่ Archive - Accept Uploads ใช้ ActiveStorage ไม่ Delete Uploads
activestorage_blobsTable Keeps Getting Bigger - Run Shared CMS Publishing Web Allow Article Segments Stored in Database Platform Successful แต Authors ส่วนใหญ่เขียน Article ใหญ่เท่าหนังสือ
pagesTable กลาย Sizeable แม้แค่ 몇 Thousand Pages - Allow User-uploaded Content ไม่ Delete Data Compliance Reasons ใช้
paranoiaDelete via Flaguser_itemsTable Grows Indefinitely ผ่าน 10M Rows โดยคุณไม่รู้
Patterns นี้มี Implications หากไม่จับทัน ถ้ามี Good View ของ Table Sizes คุณ Anticipate เมื่อ Upgrade และ Schedule Maintenance Off-peak Upgrades Less User Impact
Making Projections กลาย Easier เช่น:
- Today
eventsTable Fits in Memory Current Growth Rate ไม่ Fit in Memory ใน 7 เดือน - เรา 30% Storage Use RDS Instance Type จะ Hit 90% January ปีหน้า
- เรา Full Table Scan Query บน
paymentsCompute Function Over Every Row Where Input Depends on Query เรารู้paymentsTable Exceed 2M Rows ใน 3 สัปดาห์ และ 20M January ปีหน้า
ทั้งหมด Potential Present as Incident หรือ Outage แตถ้า Attack Early Enough Mitigate ได้ง่าย เช่น:
- Set Up Archiving Data Older Than 30 Days ใน
eventsTable - Upgrade RDS Instance ใน 4 เดือน
- Limit Full Table Scan เพิ่ม
WHERECondition Compute Function บน Smaller Subset of Rows
Gain Visibility Over Your Database Growth
ติดตาม Database Growth มี 2 ทาง:
- Install Special Tooling (like Stats for MySQL) Connect Metrics Collection Engine via Prometheus, Telegraph, หรือ Tools อื่น
- Use AppSignal โดยเฉพาะถ้าใช้อยู่แล้วสำหรับ App
AppSignal Store Several Metric Types หนึ่งคือ gauge Single Time Series Per Environment (production, staging, development) Update จาก Time to Time AppSignal Metrics Allow Tags Auto-create Tagged gauge Metrics สำหรับ Database Tables มาทำกัน:
db.row_countApproximate Number of Rows ใน Tables, Per Table (Approximates ด้านล่าง)db.data_size_bytesBytes ที่ Table ใช้db.index_size_bytesBytes ที่ Table's Indices ใช้
Note: Suffix Metric Name ด้วย Value Type ช่วยตอน Define Metric Display Separate "Data" และ "Indices" Metrics สำคัญ ถ้า Table มี Rows เยอะและ Indices หลายตัว Size ของ Indices อาจ 2-3x Size ของ Stored Data (ทุก Index Store Derived Data สร้าง Storage Overhead)
Counting Database Table Rows Quickly
"Approximate" Part ของ Row Count Essential ปกติถ้าอยาก Precise Row Count Query SELECT COUNT(1) FROM my_table แต่อาจช้ากว่าที่อยาก
ตอน COUNT Database Ensure Row Count ไม่เปลี่ยนระหว่าง Query — Lock Table หรือ Create Divergent Transaction ระหว่าง Query Runs Table ใหญ่ Query ช้ากว่า — More Rows Scanned, More Locks Accumulate
ดังนั้นตอนเราแค่อยาก "Close Enough" Approximation (สำหรับ Performance Estimation Precision 10-30k Rows Less/More Good Enough) เราใช้ Internal Database Engine Statistics Query Data Type นี้
Databases ส่วนใหญ่ Optimized Access Table Data Rows Written Out in "Pages" Engine Track Rows Assigned Pages ระดับ Insertion Order:
- Rows 1-100 on Page 1
- Rows 101-200 on Page 2
- Rows 201-300 on Page 3
Engine Knows Pages Per Table และ Rough Row Count Per Page Multiply Pages Allocated × Page Size (Rows per Page) ให้ Estimate ข้อดี: Count เร็วมาก Table ไม่ต้อง Lock ระหว่าง Query
Record Table Sizes สำหรับ MySQL
Query ที่ต้อง Run:
Grab Columns ที่สนใจ: Data_length, Index_length, และ Rows Table Size = Data_length + Index_length Approximate Row Count Based on Pages ใน Rows
Package Into Code Block Collect Data สำหรับ Entire Database ใช้ Query Methods โดยตรงจาก ActiveRecord:
Record Table Sizes สำหรับ PostgreSQL
PostgreSQL ต้อง Query แบบ Elaborate ไม่มี Shortcut Query เหมือน SHOW TABLE STATUS Query Internal PostgreSQL Tables:
Note: Account Only public Schema (Default) หาก Include Other Schemas Remove WHERE t.table_schema = 'public' และ Replace table_info.fetch('name') ด้วย table_info.fetch('full_table_name')
Make Sure Metrics Update Regularly
Block นี้ต้อง Run Regular Intervals ใส่ Sidekiq Scheduler หรือ Rake Task จาก Cron เช่นใช้ good_job เพิ่มใน "cron" Section:
Create a Dashboard
เมื่อ Data Coming In Build Dashboard Copy Dashboard นี้:
Click Add dashboard แล้ว Import dashboard ใน Modal Dialog Dashboard ให้ Graphs เหมือนนี้:

และ Table Sizes Graph:

Note: ใช้ Wildcard Tags Auto-build Graphs สำหรับ Every Table ใน Database
Interpreting the Data
ตอนดู Data Watch Out Exponential หรือ Linear Growth ใน Row Count หรือ Size — Table Getting Bigger และ Bigger
ถ้าเห็นนี้ มี Options 2 อย่าง Architect สำหรับ Unbounded Growth — รู้เมื่อ Upgrade และ Upgrade Next Best Size อีกทาง Setup Regular Deletion Task — เพื่อนร่วมงานเก่า Wander Hillen เขียนบทความยอดเยี่ยมเรื่องนี้
เช่น Screenshot ด้านบน Tables บางตัว Shrink Regularly — นั่นคือ Regular Cleanup Tasks Run เห็น Data Accumulates จน Certain Point แต Ingress of Rows Constant Sizes และ Row Counts Drop
ตราบใดมี Drops นี้ และ Data Grows Steady Rate Database จะไม่ Surprise Limit Bust
Sum Up: Avoid Data Bloat จาก Database Tables
ในบทความนี้ เราดูวิธี Gain Visibility Over Database Growth และ Keep Data Bloat Down
Data Bloat Real Risk สำหรับ Apps ที่ Successful ใน Market ด้วย Metrics สำหรับ Database Tables คุณ Anticipate Better เมื่อ Scale Database Vertically และต้อง Install Regular Stale Data Cleanups AppSignal Gauges with Tags + SQL เล็กน้อย ได้ Data นี้ใน Format สะดวกและ Pleasant
Don't Let Your Database Surprise You!
Julik Tarkhanov
Guest Author Julik Tarkhanov เป็น Staff Software Engineer at Cheddar Payments และ Author Multiple Ruby Open-source Libraries
บทความทั้งหมดโดย Julik Tarkhanov