ในบทความนี้ คุณจะเรียนรู้วิธี Test Database Performance ใน Rails และแก้ไข Common Database Performance Issues บางอย่าง
ตอน Develop Rails Application ActiveRecord เป็น Default Tool Manage Database ActiveRecord Provide Easy และ Fast Interface Query และ Insert Data ด้วย Commands เหมือน .where, .save, .create, และ .update Rails ทำงาน Convert Commands นี้เป็น SQL Queries ซึ่ง Good Thing แต่บางครั้ง Cause Performance Issues สำคัญที่คุณเข้าใจ Common Issues และ Optimize ยังไง
Quick Note on ActiveRecord in Ruby on Rails
Rails ActiveRecord เป็น Layer ใน Model-View-Controller (MVC) Manage Database โดย Represent เป็น Business Object ActiveRecord Pattern ใช้ ORM Technique Connect Objects ของ Application ไป Relational Database Table Management System
Let's Get Going!
3 Ways Identify และ Test Database Performance Issues ใน Rails
1. Run Explain on ActiveRecord Queries
Explain Statement แสดง Execution Plan ของ SQL Query — Query จะ Executed ยังไง รวม Rows Scanned, Index Used, Tables Joined ยังไง
Execution Plan ช่วย Figure Out อะไร Slow Down Query Execution โดยดู:
- Index ไหนควร Add Improve Query Performance
- Tables Joined Optimal Order ไหม ใช้
STRAIGHT_JOINForce Table Order ใน Join Statement Better Performance
Explain Works บน SELECT, DELETE, INSERT, REPLACE และ UPDATE Statements
ใช้ Explain กับ ActiveRecord Straightforward ใส่:
เพิ่ม .explain ท้าย Command ให้ Query Plan สำหรับ ActiveRecord Commands Example ข้างบน Simple Query ใช้ id (Primary Key) Query Table Output explain ใช้ pkey จากนี้ Ensure Statement Optimal และ Fast
ลองเพิ่ม .explain เข้า Slow Queries uncover Execution Order และ Index Used ถ้า Query Plan Show Seq Scan Index ไม่ Used ต้อง Query Change หรือ Add New Index
Example อีกตัวกับ Join:
User Table Join Collaborations Table ดู Query Plan Collaboration Table ใช้ seq scan Execute First — User Table ใช้ pkey Index Execute Later เพิ่ม Index บน Column user_id ใน Collaborations Table Optimize Query Explain ช่วย Break Down Query Figure Out Where Optimization Needed
2. Measure Key Database Metrics
Query Time ไม่ใช่ Metric เดียววัด Query Performant ดู Database Metrics อื่นๆ รวม:
- CPU Usage
- Memory Usage
- Disk Queue Waiting IO
- Network Bandwidth Inbound/Outbound
- Available Disk Space
- Throughput
Query อาจ Slow Down เมื่อ Metrics เหล่านี้ Over Threshold ต้อง Look Data Point Across Time Range Understand Performance Issues
Data Point ที่ต้อง Measure ขึ้นกับ Factors เยอะ:
Database Type:
- Relational
- In-memory
- No-SQL
- Data-Warehouse
Server Hosted How:
- On-premises
- On the cloud
No Single Way Monitor Database Metrics — Depends on Factors
3. Measure Rails App Performance ใช้ AppSignal
ยาก Manage All Performance Metrics Without Central Place Visibility Over All Queries Add Performance Code ทุก Code Block Cumbersome และ Unmanageable
Tools เหมือน AppSignal Integrate Performance Measurement ได้ง่าย AppSignal Support Rails Out of the Box เรียนรู้ Simple AppSignal Installation จาก 'AppSignal for Ruby' Documentation
Critical Metrics ที่ต้อง Watch:
- Slow Queries
- Database Performance Based on Throughput
- N+1 Queries
- Database Latency
- Number of Active Connections
AppSignal Dashboard อาจเป็นแบบนี้:

7 Ways Optimize Ruby on Rails Database Performance
1. Eager Loading สำหรับ N+1 Queries
N+1 Queries เป็น Common Database Performance Problem มากที่สุด Example N+1 Query ที่มี 2 Models — User และ Project:
ตอนอยากหา User และ Project Names รัน Code:
Code ข้างบน Query Database ทุก Loop Cause Performance Issues Total Queries = Number of Users + 1
Eliminate Issue Simple: Eager Load Association เพิ่ม .includes(:projects) ท้าย Query:
ตอน Execute Loop จะไม่ Query Database เพราะ Query ข้างบน Eager Load Projects:
Rails 6.1 Provide Strict Loading Ensure Association Eager Loaded Before Accessed Enable Strict Loading เพิ่ม Line ใน Model:
ตอน Access Projects Without Eager Loading Rails Throw ActiveRecord::StrictLoadingViolationError Exception
ถ้าไม่ใช่ Rails 6.1 ใช้ Gems เหมือน Bullet
2. Use Database Index
Databases Provide Indexes Retrieve Data Faster ใช้ Explain Command ครอบคลุมก่อนหน้า Figure Out Query ใช้ Proper Index ไหม
Change Slow Query ใช้ Existing Index หรือ Added Index Improve Performance
4 Index Types ใน MySQL:
- Primary Key - Index Auto Added Primary Key Ensure Unique
- Unique - Unique Key Index Ensure Items Added in Attribute Always Unique
- Index - Added Attributes Other Than Primary Key
- Full Text - Helps Query Against Character-based Data
Index Stored in B-Tree หรือ Hash Format
Indexes Added Single Field หรือ Composite Multiple Fields Composite Index Useful Optimize Queries Include Multiple Fields When Only One Index Used Require Large Dataset Scan
Example Query นี้ 2 Fields:
อาจมี Users เยอะใน Project "abc" Country Field Scanned Slow เพราะ Large Result Dataset เพิ่ม Composite Index ทั้ง Project และ Country Fields Improve Performance
Add Index Rails ด้วย ActiveRecord Migration Commands:
Single Index:
Composite Index:
3. Use Limits
Records Returned มาก Performance Slower Better Multiple Queries Than Single Query Large Dataset
Fetch Next 100 Batches ใช้ Offset:
Improve Performance Significantly One Thing: Higher Offset Query Slower Add Limit to Offset
4. Use find_each Load Large Number of Items
Iterate Records Batch ใน Rails Better Performance:
Query All Records Once Cause Memory และ Database Performance Issues
ใช้ find_each หรือ find_in_batches Improve Performance Same Operation in Batch:
Default find_each Batch 1,000 Change Batch Size Argument:
ใช้ find_in_batches ตาม Operation Need Difference: find_in_batches Yield Result as Array of Models แทน Individual Records
5. Select Required Field Using Pluck
Pluck Command Directly Convert Query Result to Array แทน ActiveRecord Object
ถ้า Query Return Large Results Pluck Improve Code Performance Pluck Select Only Required Field from Database:
Result Fetched from Index Not Main Table Effective กับ Queries Involving Sorts
6. Use Bulk Operations
Bulk Delete Delete Operation Loop ActiveRecord Object Delete Records One at a Time:
Delete Each Record Requires Many Queries Better Single Bulk delete_all Query:
Bulk Create บางคนไม่รู้ Bulk Insert กับ ActiveRecord ได้ Reduce n Queries to One ActiveRecord::Base create Method Accept Array of Hashes as Input:
7. Use In-Memory Calculation If Needed
บาง Instances In-Memory Calculation Preferable Than Querying สมมติอยากหา Countries ใน Database ที่ไม่มี User Records:
Query ข้างบน Require N Queries Get Result แทนที่จะนี้ Single Query หา Users ใน Countries ที่กำหนด Other Calculation In Memory:
Cache Reuse Request-Response Cycle Reduce Database Load บาง Cases Rails Provide 3 Caching Techniques: Page, Action, Fragment Caching (Fragment Caching Default)
Wrap Up: Optimize Ruby on Rails Performance ด้วย ActiveRecord และ AppSignal
Okay Recap! ในบทความนี้ Cover 3 Ways Identify และ Test Database Performance Issues in Rails:
- Run Explain on ActiveRecord Queries
- Measure Key Database Metrics
- Measure Rails App Performance using AppSignal
และ 7 Ways Optimize Database Performance รวม:
- Eager Loading for N+1 Queries
- Database Index
- Limits
find_eachLoad Large Number of Items- Pluck Select Required Field
- Bulk Operations
- In-Memory Calculation
Rails ทำ Super Easy และ Fast Develop App ActiveRecord Help Productivity, Reusability, Maintainability Database Code เข้าใจ ActiveRecord Queries Translate to SQL Queries Execute Important
แต่ Most Crucial Thing Optimize Rails Database Performance คือ Visibility Over Performance Data Performance Issues Common แต Resolve ได้เมื่อมี Visibility คุณต้อง Proper Monitoring Tool Provide Database Metrics เราชอบ AppSignal ;)
P.S. หากต้องการอ่านบทความ Ruby Magic ทันทีที่เผยแพร่ สมัคร Newsletter Ruby Magic ของเราและจะไม่พลาดบทความเด็ดๆ ไป!