FiveM MySQL Index คืออะไร? วิธีใช้ EXPLAIN หา Query Scan หนักและออกแบบ Index ให้ Database เร็วขึ้น

 FiveM MySQL Index คือ Index ของฐานข้อมูล MySQL/MariaDB ที่ช่วยให้ Database สามารถค้นหา Rows ที่ต้องการได้มีประสิทธิภาพขึ้นใน Query ที่เหมาะสม แทนที่จะต้องไล่อ่านข้อมูลจำนวนมากโดยไม่จำเป็น โดยเฉพาะ FiveM Server ที่มี Tables อย่าง Characters, Vehicles, Users, Logs หรือ Settings ซึ่งมีข้อมูลเพิ่มขึ้นเรื่อยๆ ตามจำนวนผู้เล่น

MariaDB มี Index หลายประเภท เช่น Primary Key, Unique Index และ Regular Index และมี EXPLAIN สำหรับดูว่า Database วางแผน Execute SELECT, UPDATE หรือ DELETE อย่างไร.

สำหรับ FiveM จุดสำคัญคือ อย่าสร้าง Index แบบเดา เพราะ Index ที่มากเกินไปมีต้นทุนตอน INSERT และการแก้ข้อมูล MariaDB เองระบุว่า Index ทุกตัวต้องได้รับการ Update เมื่อข้อมูลเปลี่ยน และ Index ที่ซ้ำซ้อนอาจไม่จำเป็น.

แนวทางที่ถูกต้องคือ:

Slow Query
↓
ดู Query จริง
↓
EXPLAIN
↓
ดู WHERE / JOIN / ORDER BY
↓
ตรวจ Index ปัจจุบัน
↓
ออกแบบ Index
↓
วัดใหม่

① Database Index คืออะไร

ลองนึกภาพ Table:

vehicles

1
2
3
4
5
...
500,000

ถ้าต้องหา:

owner = license:abc123

Database ต้องมีวิธีค้นหา Record ที่ตรงเงื่อนไข

Index เป็นโครงสร้างที่ Database Optimizer สามารถใช้เพื่อเข้าถึงข้อมูลได้มีประสิทธิภาพขึ้นใน Query Pattern ที่เหมาะสม.

② ไม่มี Index แปลว่า Query ช้าเสมอไหม

ไม่เสมอไป

Table ขนาดเล็กอาจใช้เวลาเพียงเล็กน้อยแม้ไม่มี Secondary Index

ปัญหามักชัดขึ้นเมื่อ:

Rows เพิ่ม
+
Query ถูกเรียกบ่อย
+
Filter Column ไม่มี Index ที่เหมาะสม

ดังนั้นต้องดู Execution Plan จริงด้วย EXPLAIN ไม่ควรตัดสินจากจำนวน Rows เพียงอย่างเดียว.

③ FiveM Table ไหนมักต้องคิดเรื่อง Index

ตัวอย่างเชิง Architecture:

users
characters
vehicles
player_settings
logs
transactions
sessions

โดยเฉพาะ Columns ที่ปรากฏใน:

WHERE
JOIN
ORDER BY

บ่อยๆ ควรถูกนำมาวิเคราะห์ว่า Index เหมาะสมหรือไม่

แต่ไม่ได้หมายความว่า Columns เหล่านี้ต้องมี Index ทุกตัว

④ Primary Key คือ Index หรือไม่

ใช่

MariaDB จัด Primary Key เป็น Index ประเภทหนึ่ง และ Primary Key ใช้กำหนด Row Identity หลักของ Table.

ตัวอย่าง:

CREATE TABLE `characters` (
    `id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
    `identifier` VARCHAR(64) NOT NULL,
    `firstname` VARCHAR(50) NOT NULL,
    `lastname` VARCHAR(50) NOT NULL,

    PRIMARY KEY (`id`)
);

⑤ UNIQUE INDEX คืออะไร

Unique Index ใช้บังคับไม่ให้ค่าหรือชุดค่าที่อยู่ภายใต้ Index ซ้ำกันตามข้อกำหนดของ Database

MariaDB แยก Unique Index ออกจาก Regular Index และ Primary Key ใน Index Guide.

ตัวอย่าง:

CREATE UNIQUE INDEX `uq_users_identifier`
ON `users` (`identifier`);

เหมาะเมื่อ Business Rule ระบุว่า Identifier นั้นต้องไม่ซ้ำ

⑥ Regular Index คืออะไร

Regular Index ใช้ช่วยการค้นหาโดยไม่ได้บังคับค่าต้อง Unique

ตัวอย่าง:

CREATE INDEX `idx_vehicles_owner`
ON `vehicles` (`owner`);

MariaDB รองรับการเพิ่ม Index ผ่าน CREATE INDEX.

⑦ FiveM Vehicle Table ตัวอย่าง

สมมติ:

CREATE TABLE `vehicles` (
    `id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
    `owner` VARCHAR(64) NOT NULL,
    `model` VARCHAR(60) NOT NULL,
    `stored` TINYINT NOT NULL DEFAULT 1,
    `garage_id` INT NULL,
    `created_at` DATETIME NOT NULL,

    PRIMARY KEY (`id`)
);

แล้ว Resource ใช้:

SELECT
    `id`,
    `model`,
    `stored`
FROM `vehicles`
WHERE `owner` = ?;

ถ้า owner เป็น Column ที่ Query นี้ใช้ตลอด ก็ควรนำมาวิเคราะห์เรื่อง Index

⑧ วิธีสร้าง Index ให้ owner

CREATE INDEX `idx_vehicles_owner`
ON `vehicles` (`owner`);

แต่ก่อนเพิ่มใน Production ควรตรวจว่า:

Index นี้มีอยู่แล้วหรือไม่
มี Composite Index ที่ขึ้นต้นด้วย owner หรือไม่
Query ใช้งานจริงอย่างไร

เพราะ MariaDB ระบุว่า INDEX(a,b) สามารถรองรับการค้นหาบางแบบที่ INDEX(a) รองรับได้ จึงอาจไม่จำเป็นต้องเก็บ Index ซ้ำทั้งสองชุด.

⑨ ดู Index ที่มีอยู่ยังไง

MariaDB รองรับ Index Metadata ผ่านคำสั่งในกลุ่ม Index Management และ Guide ครอบคลุม SHOW INDEX สำหรับตรวจ Index ของ Table.

ตัวอย่าง:

SHOW INDEX
FROM `vehicles`;

ก่อนสร้าง Index ใหม่ควรเปิดดูรายการนี้ก่อนเสมอ

⑩ EXPLAIN คืออะไร

EXPLAIN เป็นคำสั่งของ MariaDB สำหรับดูข้อมูลว่า Database วางแผน Execute Query อย่างไร

ปัจจุบันใช้กับ:

SELECT
UPDATE
DELETE

ได้.

ตัวอย่าง:

EXPLAIN
SELECT
    `id`,
    `model`
FROM `vehicles`
WHERE `owner` = 'license:example';

⑪ ทำไม EXPLAIN สำคัญกว่าเดา

เพราะ Developer อาจคิดว่า:

ฉันสร้าง Index แล้ว
=
Database ใช้มันแน่นอน

แต่ Optimizer เป็นผู้เลือก Execution Plan

จึงต้องตรวจว่า Query Plan แสดงอะไรจริง ไม่ใช่ตัดสินจาก Schema อย่างเดียว.

⑫ EXPLAIN ควรใช้กับ Query จริง

ถ้า Resource มี Query:

SELECT
    `id`,
    `model`,
    `stored`
FROM `vehicles`
WHERE `owner` = ?
  AND `stored` = ?
ORDER BY `id` DESC;

เวลาวิเคราะห์ควรใช้ Query Structure เดียวกัน

ไม่ใช่ทดสอบเพียง:

SELECT *
FROM `vehicles`;

เพราะ Execution Plan แตกต่างกัน

⑬ EXPLAIN ดูอะไรเป็นหลัก

สำหรับ Developer FiveM มือใหม่ ให้เริ่มจากดูแนวคิดเหล่านี้:

Table ไหนถูกอ่าน
↓
Index Candidate มีอะไร
↓
Database เลือก Index ไหน
↓
ต้องอ่าน Rows มากแค่ไหน
↓
มี Operations เพิ่มเติมหรือไม่

MariaDB EXPLAIN ให้ข้อมูลเกี่ยวกับ Execution Plan ที่ Optimizer เลือกใช้.

⑭ type ใน EXPLAIN คืออะไร

EXPLAIN Result มีข้อมูลเกี่ยวกับวิธีที่ Database เข้าถึง Table

ไม่ควรจำเพียงว่า:

ALL = แย่เสมอ

เพราะ Table ขนาดเล็กหรือ Query บางประเภท Optimizer อาจเลือก Full Scan อย่างสมเหตุสมผล

ต้องพิจารณาร่วมกับจำนวน Rows และ Query Context

⑮ possible_keys คืออะไร

ใน Execution Plan สามารถมีข้อมูลเกี่ยวกับ Index ที่เป็น Candidate สำหรับ Query

ถ้า Query:

WHERE `owner` = ?

แต่ไม่มี Index ที่เกี่ยวข้องเลย นั่นเป็นสัญญาณให้ตรวจ Schema ต่อ

อย่างไรก็ตามการมี Candidate ไม่ได้หมายความว่า Optimizer จะเลือกใช้จริง

⑯ key คืออะไร

แนวคิดคือ Index ที่ Execution Plan เลือกใช้จริงสำหรับขั้นตอนนั้น

ถ้า Developerคาดหวัง:

idx_vehicles_owner

แต่ Plan ไม่เลือก อาจต้องตรวจ:

Query Pattern
Column Selectivity
Table Size
Index Statistics
Composite Index
Data Distribution

แทนการ Force แบบสุ่ม

⑰ rows สำคัญอย่างไร

ค่า Estimate เกี่ยวกับจำนวน Rows ที่ต้องตรวจช่วยให้เห็นว่า Query อาจต้องอ่านข้อมูลมากแค่ไหน

หาก Table ใหญ่มากและ Query ต้องตรวจ Records จำนวนมาก นั่นเป็นจุดที่ควรวิเคราะห์ Index หรือ Query Structure เพิ่ม

⑱ Full Table Scan คืออะไร

แนวคิด:

ต้องหา Owner คนเดียว

แต่ Database
↓
อ่าน Table จำนวนมาก
↓
ตรวจ Row ทีละส่วน

อาจเกิดขึ้นหากไม่มี Index ที่เหมาะสมหรือ Optimizerเห็นว่า Scan Table คุ้มกว่า

อย่าด่วนสรุปว่า Full Scan ทุกครั้งคือ Bug ต้องดู Table และ Workload จริง

⑲ Index ช่วย WHERE อย่างไร

ตัวอย่าง Query:

SELECT
    `id`,
    `model`
FROM `vehicles`
WHERE `owner` = ?;

Index:

CREATE INDEX `idx_vehicles_owner`
ON `vehicles` (`owner`);

สามารถเป็น Candidate ให้ Optimizer ใช้ค้นหาตาม owner โดยตรงตาม Index Design.

⑳ Composite Index คืออะไร

Composite หรือ Compound Index คือ Index ที่มีมากกว่าหนึ่ง Column

MariaDB ยกตัวอย่างลักษณะ:

INDEX(last_name, first_name)

เป็น Composite Index.

FiveM ตัวอย่าง:

CREATE INDEX `idx_vehicles_owner_stored`
ON `vehicles` (`owner`, `stored`);

㉑ Composite Index เหมาะกับ Query แบบไหน

สมมติ Resource ใช้:

SELECT
    `id`,
    `model`
FROM `vehicles`
WHERE `owner` = ?
  AND `stored` = ?;

Composite Index:

(owner, stored)

อาจเหมาะกว่า Single-column Index บางแบบ

แต่ต้องตรวจด้วย EXPLAIN และ Data Distribution จริง.

㉒ Column Order สำคัญไหม

สำคัญ

Composite Index:

INDEX(owner, stored)

และ:

INDEX(stored, owner)

ไม่ควรถูกมองว่าเหมือนกันทุกกรณี

MariaDB อธิบาย Composite Index ผ่านลำดับ Columns และการเดิน B-tree ของ Index โดยตรง.

㉓ Leftmost Prefix แนวคิดคืออะไร

ถ้ามี:

INDEX(owner, stored)

Query ที่ Filter ตาม owner สามารถได้รับประโยชน์จากส่วนเริ่มต้นของ Composite Index ในหลายกรณี

MariaDB ระบุว่า INDEX(a,b) สามารถค้นหาสิ่งที่ INDEX(a) ทำได้ในบริบทการออกแบบ Index ที่เหมาะสม.

ดังนั้นการมี:

INDEX(owner)
INDEX(owner, stored)

พร้อมกันอาจซ้ำซ้อน

㉔ Index ซ้ำซ้อนคืออะไร

ตัวอย่าง:

INDEX(owner)
INDEX(owner, stored)

MariaDB ระบุว่าหากมี INDEX(a,b) ก็ไม่จำเป็นต้องมี INDEX(a) แยกเสมอไป เพราะ Index ที่ยาวกว่าสามารถรองรับ Prefix นั้นได้.

ก่อนลบ Index ต้องตรวจ Queries ทั้งระบบก่อน

㉕ ทำไม Index เยอะเกินไปไม่ดี

เพราะ Index ไม่ได้มี Cost เฉพาะตอน Read

เมื่อมี:

INSERT
UPDATE
DELETE

Database ต้องรักษา Index ที่เกี่ยวข้องด้วย

MariaDB เตือนว่า Index มากขึ้นหมายถึง INSERT ช้าลง และให้ Rule of Thumb เกี่ยวกับการจำกัดจำนวน Index ที่ไม่จำเป็น.

㉖ อย่า Index ทุก Column

ตัวอย่าง Table:

id
owner
model
stored
garage_id
color
label
created_at
updated_at

การทำ:

INDEX(owner)
INDEX(model)
INDEX(stored)
INDEX(garage_id)
INDEX(color)
INDEX(label)
INDEX(created_at)
INDEX(updated_at)

โดยไม่ดู Query จริงอาจสร้าง Index จำนวนมากที่แทบไม่ได้ใช้

ให้เริ่มจาก Query Pattern

㉗ Query Pattern คืออะไร

คือรูปแบบ Queries ที่ Resource ใช้งานจริง

เช่น Garage Resource อาจมี:

WHERE owner = ?

และ:

WHERE owner = ?
  AND stored = ?

และ:

WHERE garage_id = ?
  AND stored = ?

Index Design จึงต้องดู Queries ทั้งชุด ไม่ใช่ Query เดียว

㉘ Covering Index คืออะไร

MariaDB อธิบายว่า Covering Index คือ Index ที่มี Columns ที่ SELECT ต้องการครบ ทำให้ Query บางประเภทสามารถอ่านข้อมูลจาก Index B-tree ได้โดยไม่ต้องย้อนกลับไปอ่าน Row Data เพิ่ม.

ตัวอย่างเชิงแนวคิด:

SELECT
    `owner`,
    `stored`
FROM `vehicles`
WHERE `owner` = ?;

Index:

(owner, stored)

อาจทำหน้าที่เป็น Covering Index สำหรับ Query ที่เหมาะสม

㉙ ต้องทำ Covering Index ทุก Query ไหม

ไม่

MariaDB เตือนเรื่อง Index จำนวนมากและต้นทุนต่อ Writes เช่นกัน.

ดังนั้นไม่ควรสร้าง Index ใหญ่เพื่อ Cover ทุก SELECT โดยอัตโนมัติ

ควรใช้กับ Query ที่:

เรียกบ่อย
+
มี Performance Impact
+
วัดแล้วคุ้ม

㉚ ORDER BY เกี่ยวกับ Index ไหม

เกี่ยวข้องได้

ตัวอย่าง:

SELECT
    `id`,
    `message`,
    `created_at`
FROM `logs`
WHERE `identifier` = ?
ORDER BY `created_at` DESC
LIMIT 50;

อาจต้องพิจารณา Index ที่สัมพันธ์กับทั้ง Filtering และ Ordering

แต่ต้องใช้ EXPLAIN ตรวจ Execution Plan ก่อนตัดสินใจ.

㉛ ตัวอย่าง Composite Index สำหรับ Logs

สมมติ Query ใช้ตลอด:

WHERE `identifier` = ?
ORDER BY `created_at` DESC

อาจทดลอง Index:

CREATE INDEX `idx_logs_identifier_created`
ON `logs` (`identifier`, `created_at`);

จากนั้น:

EXPLAIN
SELECT
    `id`,
    `message`,
    `created_at`
FROM `logs`
WHERE `identifier` = 'license:example'
ORDER BY `created_at` DESC
LIMIT 50;

แล้วเปรียบเทียบ Plan ก่อน/หลัง

㉜ JOIN เกี่ยวกับ Index อย่างไร

สมมติ:

SELECT
    c.`firstname`,
    v.`model`
FROM `characters` c
JOIN `vehicles` v
    ON v.`character_id` = c.`id`
WHERE c.`identifier` = ?;

Columns ที่ใช้ Join และ Filter เป็น Candidate สำคัญในการวิเคราะห์ Index

แต่ยังต้องดู Execution Plan จริงด้วย

㉝ Foreign Key มี Index หรือไม่

MariaDB ระบุว่า Foreign Key ต้องมี Index ที่เหมาะสม และถ้าไม่มี Index ที่รองรับ Foreign Key MariaDB สามารถสร้าง Index ให้โดยอัตโนมัติในบางกรณี.

ดังนั้นก่อนสร้าง Index บน Foreign Key Column ซ้ำ ให้ตรวจ Existing Indexes ก่อน

㉞ LIKE '%keyword%' ใช้ Index ธรรมดาได้ดีไหม

Query ที่ค้นหา Text แบบมี Wildcard นำหน้ามี Characteristics ต่างจาก Equality Lookup

ถ้าต้องค้นหาข้อความเต็มรูปแบบจำนวนมาก MariaDB มี FULLTEXT Index และ MATCH() ... AGAINST() สำหรับ Full-text Search โดยเฉพาะ.

อย่าพยายามแก้ Search ทุกประเภทด้วย Regular Index อย่างเดียว

㉟ FULLTEXT Index คืออะไร

MariaDB มี FULLTEXT Index สำหรับการค้นหาข้อความภายใน Text Fields โดยรองรับ Full-text Search Modes หลายแบบ.

อย่างไรก็ตาม FiveM Resource ส่วนใหญ่ไม่ได้ต้องใช้ Full-text Index เว้นแต่มีระบบ Search เช่น:

Admin Logs Search
Message Search
Large Text Records

㊱ Index Statistics คืออะไร

MariaDB Optimizer ใช้ Index Statistics เป็นข้อมูลช่วยเลือก Execution Plan

MariaDB ระบุว่า Index Statistics มีความสำคัญต่อการตัดสินใจของ Query Optimizer.

ถ้า Statistics ไม่สะท้อนข้อมูลปัจจุบัน Optimizer อาจเลือก Plan ที่ไม่เหมาะกับ Distribution ใหม่ได้

㊲ ANALYZE TABLE คืออะไร

MariaDB มี:

ANALYZE TABLE `vehicles`;

สำหรับวิเคราะห์และจัดเก็บ Key Distribution/Statistics ที่ Optimizer ใช้ในการเลือก Execution Plan.

ไม่ใช่คำสั่งที่ต้อง Run ทุก Query

ใช้เมื่อมีเหตุผลด้าน Statistics และ Database Maintenance

㊳ เพิ่ม Index แล้ว EXPLAIN ยังไม่ใช้เพราะอะไร

สาเหตุที่เป็นไปได้ เช่น:

Table เล็ก
Index Selectivity ต่ำ
Statistics
Query Structure
Data Distribution
มี Index อื่นเหมาะกว่า

Optimizer เป็นผู้ตัดสิน Plan

จึงไม่ควรบังคับว่า Index ต้องถูกใช้เพียงเพราะเราเพิ่งสร้างมัน

㊴ Selectivity คืออะไร

แนวคิดง่ายๆ คือ Column สามารถแบ่ง Rows ออกจากกันได้มากแค่ไหน

ตัวอย่าง:

owner
= มีค่าหลากหลายมาก

stored
= มีเพียง 0 / 1

ในหลาย Dataset owner มีความเฉพาะเจาะจงมากกว่า stored

นี่เป็นหนึ่งในเหตุผลที่ Column Order ของ Composite Index ต้องอิงข้อมูลจริง ไม่ใช่ชื่อ Column

㊵ Index บน Boolean Column ดีไหม

ไม่สามารถตอบว่า “ดีเสมอ” หรือ “ไม่ดีเสมอ”

ตัวอย่าง:

stored = 0 / 1

มี Cardinality ต่ำ

Index เดี่ยวบน Column นี้อาจไม่คุ้มในหลาย Workload แต่:

INDEX(owner, stored)

อาจมีประโยชน์กับ Query ที่ Filter Owner ก่อนแล้วตามด้วย Stored

ต้องดู Query และ EXPLAIN

㊶ Query Garage ตัวอย่างก่อน Optimize

SELECT
    `id`,
    `model`,
    `stored`
FROM `vehicles`
WHERE `owner` = ?
  AND `stored` = ?
ORDER BY `id` DESC;

ก่อนเพิ่ม Index:

EXPLAIN
SELECT
    `id`,
    `model`,
    `stored`
FROM `vehicles`
WHERE `owner` = 'license:example'
  AND `stored` = 1
ORDER BY `id` DESC;

เก็บ Baseline ก่อน

㊷ เพิ่ม Composite Index

CREATE INDEX `idx_vehicles_owner_stored`
ON `vehicles` (`owner`, `stored`);

MariaDB รองรับ Composite Index และ CREATE INDEX อย่างเป็นทางการ.

จากนั้น Run EXPLAIN ใหม่

㊸ อย่าดูแค่ EXPLAIN ต้องวัด Query Time ด้วย

Execution Plan สำคัญ แต่เป้าหมายสุดท้ายคือ Performance ของ Workload จริง

สำหรับ FiveM ที่ใช้ oxmysql สามารถดู Query Speeds ผ่าน Debug UI หรือ Server Console เมื่อเปิด mysql_debug; oxmysql ระบุว่าความเร็วจริงขึ้นกับ Hardware, Database Settings, Version และ Current Workload.

ดังนั้นใช้:

EXPLAIN
+
Query Timing

ร่วมกัน

㊹ mysql_debug ใช้ร่วมกับ Index Optimization อย่างไร

Workflow:

mysql_debug
↓
เจอ Query ช้า

EXPLAIN
↓
ดู Plan

Index
↓
แก้ Schema

mysql_debug
↓
วัดใหม่

oxmysql ระบุว่า Query Speed จริงสามารถดูจาก Debug UI และ Console เมื่อ mysql_debug เปิด.

㊺ FiveM Profiler ยังจำเป็นไหม

จำเป็นเมื่อไม่แน่ใจว่าปัญหาอยู่:

Database
หรือ
Resource Code

Cfx.re Profiler ใช้หา Server Hitch ผ่าน CPU Time Spikes และสามารถเจาะ Resource/Thread ที่ใช้เวลามากได้.

และ Cfx.re ระบุว่า SQL Query ที่ทำงานช้าสามารถเป็นหนึ่งในสาเหตุ Hitch Warning ได้.

㊻ Query เร็วแต่ Resource ยัง Hitch

สมมติ:

Database Query = 10 ms

Resource Tick = 300 ms

ปัญหาอาจอยู่ที่:

Loop Results
JSON Decode
Nested Loop
Entity Processing
Event Dispatch

ไม่ใช่ Index

Profiler จึงช่วยแยก Bottleneck

㊼ Query ช้าแต่ CPU Resource ไม่สูง

ก็ยังเป็นไปได้

Database Operation อาจต้องรอผลโดยไม่ได้สร้าง CPU Spike แบบเดียวกับ Heavy Loop

จึงต้องตรวจ:

oxmysql Timing
+
EXPLAIN
+
Database Monitoring
+
FiveM Profiler

ร่วมกัน

㊽ MySQL.prepare แทน Index ได้ไหม

ไม่ได้

oxmysql ระบุว่า MySQL.prepare เหมาะสำหรับ Queries ที่ถูกเรียกบ่อยและช่วยให้ Query Execution แบบเดิมซ้ำๆ เร็วขึ้น.

แต่ถ้า SQL ต้อง Scan Records จำนวนมหาศาลเพราะไม่มี Index ที่เหมาะสม การเปลี่ยน API เป็น prepare ไม่ได้แทน Query Optimization

㊾ Prepare + Index ใช้ร่วมกันได้ไหม

ได้

ตัวอย่าง:

local vehicles =
    MySQL.prepare.await(
        [[
            SELECT
                `id`,
                `model`,
                `stored`
            FROM `vehicles`
            WHERE `owner` = ?
              AND `stored` = ?
        ]],
        {
            identifier,
            1
        }
    )

และ Database มี:

CREATE INDEX `idx_vehicles_owner_stored`
ON `vehicles` (`owner`, `stored`);

แต่ต้องวัดว่าการใช้ Prepare มีประโยชน์จริงกับ Frequency ของ Query นั้น.

㊿ อย่าปรับ Query API ก่อนรู้ Bottleneck

คำถามที่ควรถามคือ:

Query ช้าเพราะอะไร?

① SQL Structure?
② Index?
③ Result ใหญ่?
④ ถูกเรียกบ่อย?
⑤ Database Load?
⑥ FiveM Resource Code?

แก้ตามต้นเหตุ

ไม่ใช่เปลี่ยน:

query
→ prepare

ทุกตัวแล้วหวังว่า Database จะเร็วขึ้นทั้งหมด

51. Index กับ SELECT * เกี่ยวข้องไหม

ถ้า Resource ต้องใช้เพียง 3 Columns:

SELECT
    `id`,
    `model`,
    `stored`
FROM `vehicles`
WHERE `owner` = ?;

ชัดกว่า:

SELECT *
FROM `vehicles`
WHERE `owner` = ?;

นอกจากนี้การเลือก Columns ที่เหมาะสมยังเปิดโอกาสให้บาง Query ใช้ Covering Index ได้เมื่อ Index มีข้อมูลที่ต้องการครบ.

52. LIMIT ช่วย Index ไหม

LIMIT มีหน้าที่จำกัดจำนวน Rows ที่คืน ไม่ใช่สร้าง Index

ตัวอย่าง:

SELECT
    `id`,
    `message`,
    `created_at`
FROM `logs`
WHERE `identifier` = ?
ORDER BY `created_at` DESC
LIMIT 50;

Index และ LIMIT สามารถทำงานร่วมกันใน Query Plan ที่เหมาะสม แต่ยังต้องตรวจ EXPLAIN

53. Pagination สำคัญกับ Logs Table

Table Logs สามารถโตมากตามเวลา

แทนที่จะ:

เปิด Admin UI
↓
โหลด Logs ทั้งหมด

ใช้:

50 Rows ต่อหน้า

จะลด Result Set ที่ Database และ Resource ต้องจัดการ

Index ที่สัมพันธ์กับ Filter/Order สามารถช่วย Query Pagination ได้ใน Design ที่เหมาะสม

54. OFFSET เยอะมี Cost ได้ไหม

Query รูปแบบ:

LIMIT 50 OFFSET 500000

อาจมี Performance Characteristics ที่ต่างจาก Page แรกมาก

สำหรับ Logs ขนาดใหญ่ อาจพิจารณา Keyset/Cursor Pagination เช่นอิง id หรือ Timestamp ตาม Architecture

แต่ต้องออกแบบกับ Query และ UX จริง

55. Index Primary Key ใช้ Pagination ได้อย่างไร

ถ้า Logs มี:

id

เป็น Primary Key

สามารถออกแบบ:

SELECT
    `id`,
    `message`
FROM `logs`
WHERE `id` < ?
ORDER BY `id` DESC
LIMIT 50;

สำหรับ Cursor Pagination ในบาง Use Case

Primary Key ถูก Index อยู่แล้วตาม Database Design.

56. Index กับ VARCHAR ยาวมากควรระวังอะไร

Columns ประเภท String ที่ใช้เป็น Index ต้องพิจารณา:

Data Length
Character Set
Selectivity
Query Pattern

อย่าเพิ่ม Index ลง Text Fields ทุกตัว

ถ้าค้น Full Text จริงควรพิจารณา FULLTEXT ตามประเภทข้อมูล.

57. FiveM Identifier ควร Index ไหม

ถ้า Table ใช้:

WHERE `identifier` = ?

อย่างต่อเนื่อง เช่นค้น Character หรือ User Record การมี Index ที่เหมาะสมบน Identifier เป็น Candidate ที่ควรวิเคราะห์

ตัวอย่าง:

CREATE INDEX `idx_characters_identifier`
ON `characters` (`identifier`);

แล้วตรวจด้วย EXPLAIN

58. Internal Character ID ยังสำคัญไหม

ควรมี Persistent Application ID เช่น:

character_id

เป็น Primary Key ของ Character

แทนการใช้ FiveM Runtime Server ID

ตัวอย่าง:

PRIMARY KEY (`id`)

ช่วยให้ Relations เช่น Vehicles, Settings หรือ Statistics อ้าง Character เดิมได้อย่างชัดเจน

59. Foreign Key กับ Character ID

ตัวอย่าง:

characters.id
↓
vehicles.character_id

Foreign Key สามารถใช้รักษา Referential Integrity ตาม Database Design และ MariaDB กำหนดเรื่อง Index ของ Foreign Key ไว้ด้วย.

อย่างไรก็ตาม Resources FiveM แต่ละชุดมี Schema Architecture ต่างกัน ควรดู Framework Compatibility ก่อนเพิ่ม Constraints ลง Production

60. SHOW INDEX_STATISTICS คืออะไร

MariaDB มี SHOW INDEX_STATISTICS สำหรับดู Statistics การใช้งาน Index เพื่อช่วยวิเคราะห์ว่า Index ใดถูกใช้งานบ่อย.

ตัวอย่าง:

SHOW INDEX_STATISTICS;

ความพร้อมใช้งานและ Configuration ของ Statistics ต้องตรวจตาม MariaDB Version/Environment ที่ใช้

61. Index ไม่เคยถูกใช้งานควรลบทันทีไหม

ไม่

อาจมี Query ที่:

ใช้เฉพาะ Maintenance
ใช้เดือนละครั้ง
ใช้ตอน Migration
ใช้ตอน Admin Action

และ Statistics Window อาจยังไม่ครอบคลุม

ก่อน Drop Index ต้องตรวจ:

Schema
Queries ทั้งระบบ
Framework
Migration Scripts
Production Workload

ให้ครบ

62. Ignored Index คืออะไร

MariaDB รองรับ Ignored Indexes ซึ่ง Index ยังถูกเก็บและ Maintain อยู่ แต่ Optimizer จะไม่ใช้ Index นั้นในการวาง Query Plan.

แนวคิดนี้มีประโยชน์ในงาน Database Tuning บางประเภทสำหรับทดสอบผลของการไม่ใช้ Index ก่อนตัดสินใจลบจริง

63. ANALYZE TABLE หลังข้อมูลเปลี่ยนมากช่วยอะไร

ANALYZE TABLE อัปเดต Key Distribution/Index Statistics ที่ Optimizer ใช้สำหรับเลือก Execution Plan.

หาก Data Distribution เปลี่ยนมากและ Plan ดูผิดปกติ นี่เป็นเครื่องมือหนึ่งที่ Database Administrator สามารถพิจารณาได้

ไม่ควร Run ต่อเนื่องทุกไม่กี่วินาที

64. ก่อน CREATE INDEX Production ควรทำอะไร

Checklist:

① Backup Database
② ตรวจ Table Size
③ ตรวจ Existing Indexes
④ จด Query Timing
⑤ Run EXPLAIN
⑥ ทดสอบ Index บน Staging
⑦ Run EXPLAIN ใหม่
⑧ วัด Query Timing ใหม่
⑨ ตรวจ Write Performance
⑩ ค่อยขึ้น Production

MariaDB ระบุว่า CREATE INDEX ถูก Map ไปเป็น ALTER TABLE Operation และบาง Index Changes สามารถเกี่ยวข้องกับการเปลี่ยนโครงสร้าง Table.

65. CREATE INDEX บน Table ใหญ่ควรระวัง

อย่ารัน DDL บน Production Table ขนาดใหญ่แบบสุ่มในช่วง Player เยอะ

เพราะ Index Creation เป็น Schema Operation และผลกระทบขึ้นกับ:

MariaDB Version
Storage Engine
Table Size
Operation
Server Resources

ควรทดสอบและมี Maintenance Plan

66. DROP INDEX ควรระวังเหมือนกัน

ก่อนลบ Index ต้องรู้ว่า Resource หรือ Query ใดพึ่ง Index นั้น

ทำ:

SHOW INDEX
↓
ตรวจ Queries
↓
EXPLAIN
↓
Benchmark
↓
Backup

ก่อน

Index ที่ดูซ้ำอาจยังมีความแตกต่างใน Query Pattern บางแบบ

67. Slow Query หลังเพิ่ม Index แต่ไม่ดีขึ้น

ตรวจ:

EXPLAIN ใช้ Index หรือไม่
↓
Result ใหญ่หรือไม่
↓
Query Count สูงหรือไม่
↓
Database CPU สูงหรือไม่
↓
Resource Process Result หนักหรือไม่
↓
Network Database Remote หรือไม่

อย่าซ้อน Index เพิ่มไปเรื่อยๆ

68. Slow Query หายแต่ INSERT ช้าลงเกิดจากอะไร

Index เพิ่มขึ้นทำให้ Write Operations ต้อง Maintain Index เพิ่ม

MariaDB เตือนว่า More Indexes สามารถทำให้ Inserts ช้าลง.

จึงต้องวัดทั้ง:

Read
และ
Write

ไม่ใช่ Optimize SELECT อย่างเดียว

69. Query ใช้ owner + stored + garage_id ต้องสร้าง Index 3 ตัวไหม

ไม่จำเป็น

สมมติ Queries:

WHERE owner = ?
  AND stored = ?
  AND garage_id = ?

อาจต้องวิเคราะห์ Composite Index

เช่น:

(owner, stored, garage_id)

แต่ Column Order และจำนวน Columns ต้องอิง Queries อื่นด้วย

MariaDB แนะนำสร้าง Index จาก SELECT Pattern จริงและเตือนเรื่อง Redundant/Excessive Indexes.

70. Index Design สำหรับ FiveM ควรเริ่มจากไหน

เริ่มจาก Resources ที่สร้าง Query มากที่สุด เช่น:

Character Load
Garage
Inventory Metadata
Admin Logs
Player Settings

แล้วเรียงตาม:

Query Frequency
×
Query Time
×
Player Count

Query 2 ms ที่เรียกหนึ่งล้านครั้งอาจสำคัญกว่า Query 100 ms ที่เรียกวันละครั้ง

71. oxmysql Debug ช่วยดู Query Count ได้ไหม

oxmysql Debug UI แสดงข้อมูล Query/Resource Statistics และ Benchmark Documentation ระบุว่าความเร็ว Query จริงดูได้จาก Debug UI หรือ Console เมื่อ mysql_debug ทำงาน.

จึงเหมาะกับการหา:

Resource ไหน Query เยอะ
Query ไหนช้า

ก่อนออกแบบ Index

72. FiveM Hitch Warning กับ Index

Cfx.re ระบุว่า Hitch Warning สามารถเกิดจาก SQL Queries ที่ใช้เวลานาน รวมถึง Unoptimized Loops.

ดังนั้น Index เป็นเพียงหนึ่งในเครื่องมือแก้ Database-side Bottleneck

หาก Profiler ชี้ว่า Resource ใช้ CPU กับ Loop มากกว่า SQL การเพิ่ม Index จะไม่แก้ Loop

73. วิธีทดสอบ Before/After Index

ก่อน:

Query = 180 ms
Rows = ...
Plan = ...

เพิ่ม Index

หลัง:

Query = 12 ms
Rows = ...
Plan = ...

ตัวเลขต้องมาจาก Server จริง ไม่ใช่ Copy จาก Tutorial

oxmysql ระบุว่า Performance แตกต่างตาม Hardware, Settings, Version และ Workload.

74. อย่า Benchmark ด้วย Database ว่างเปล่าอย่างเดียว

Query ที่มี:

100 Rows

อาจดูเร็วมาก

แต่ Production:

5,000,000 Rows

อาจต่างกันชัดเจน

ควร Test ด้วย Data Size/Distribution ใกล้ Production

75. SQL Injection เกี่ยวกับ Index ไหม

เป็นคนละเรื่อง

Index:

Performance

Parameterized Query:

Query Safety / Correct Parameter Handling

อย่าเปลี่ยนจาก Parameterized Query เป็น String Concatenation เพียงเพราะกำลัง Optimize SQL

76. Index ไม่แก้ Query ที่ถูกเรียกผิด Architecture

ตัวอย่าง:

ทุก Frame
↓
SELECT WHERE owner = ?

ต่อให้ Queryเร็วมาก การ Query Database ทุก Frame ก็ยังเป็น Architecture ที่ควรแก้

ควรพิจารณา:

Load Once
↓
Cache
↓
Update on Change

ตาม Use Case

77. Index ไม่แทน Cache

Database:

Persistent Source

Index:

ช่วย Database Lookup

Cache:

ลดการอ่าน Database ซ้ำ

ทั้งสามทำหน้าที่ต่างกัน

Resource ที่ออกแบบดีอาจใช้ทั้งสามอย่างร่วมกัน

78. Index ไม่แทน Pagination

ถ้า Queryคืน:

500,000 Rows

แม้ค้นหาได้เร็ว Resource ก็ยังต้อง:

ส่งข้อมูล
Allocate Memory
Loop Result
Serialize

Pagination หรือจำกัดข้อมูลที่คืนยังมีความสำคัญ

79. Index ไม่แทน Query Design

ตัวอย่างที่ควรตรวจ:

SELECT *
FROM giant_table;

การสร้าง Indexไม่ได้ช่วย Query ที่ต้องการทุก Row อย่างมหัศจรรย์

ต้องถามว่า Resource ต้องใช้ข้อมูลทั้งหมดจริงหรือไม่

80. ตัวอย่าง Complete Optimization Flow

เริ่มจาก oxmysql พบ:

garage query = slow

SQL:

SELECT
    `id`,
    `model`,
    `stored`
FROM `vehicles`
WHERE `owner` = ?
  AND `stored` = ?;

ทำ:

① mysql_debug
② ดู Timing
③ EXPLAIN
④ SHOW INDEX
⑤ ตรวจ Existing Index
⑥ เพิ่ม Composite Index ใน Test DB
⑦ EXPLAIN ใหม่
⑧ Benchmark
⑨ FiveM Profiler
⑩ Load Test

นี่เป็น Flow ที่ควรใช้มากกว่าการเพิ่ม Index ทันที

81. ตัวอย่าง Index สำหรับ Character Selection

Query:

SELECT
    `id`,
    `firstname`,
    `lastname`
FROM `characters`
WHERE `identifier` = ?
ORDER BY `id`;

Candidate:

CREATE INDEX `idx_characters_identifier`
ON `characters` (`identifier`);

จากนั้นตรวจด้วย:

EXPLAIN
SELECT
    `id`,
    `firstname`,
    `lastname`
FROM `characters`
WHERE `identifier` = 'license:example'
ORDER BY `id`;

82. ตัวอย่าง Index สำหรับ Player Settings

หากหนึ่ง Player มีเพียงหนึ่ง Settings Row และ Identifier ต้อง Unique:

CREATE UNIQUE INDEX `uq_settings_identifier`
ON `player_settings` (`identifier`);

Unique Index มีทั้งบทบาท Lookup และ Constraint ไม่ให้ค่าซ้ำตาม Database Definition.

83. ตัวอย่าง Index สำหรับ Logs

Query:

SELECT
    `id`,
    `event`,
    `created_at`
FROM `logs`
WHERE `identifier` = ?
ORDER BY `created_at` DESC
LIMIT 100;

Candidate:

CREATE INDEX `idx_logs_identifier_created`
ON `logs` (`identifier`, `created_at`);

จากนั้นใช้ EXPLAIN และ Query Timing ยืนยัน

84. FiveM MySQL Index ทำ Server เร็วขึ้นแน่นอนไหม

ไม่สามารถรับประกันทุก Query

Index ช่วยเฉพาะ Query Pattern ที่ Optimizer สามารถใช้ Index นั้นได้อย่างเหมาะสม และ Index เองเพิ่มต้นทุนของ Write Operations.

ดังนั้นคำตอบที่ถูกต้องคือ:

Index ที่ออกแบบถูกกับ Query ที่ถูกต้องสามารถช่วยได้มาก แต่ Index ที่ผิดหรือเกินจำเป็นก็สร้าง Cost เพิ่มได้

Checklist FiveM MySQL Index

ก่อนเพิ่ม Index ตรวจ:

  1. Query ไหนช้า

  2. Resource ไหนเรียก

  3. Query ถูกเรียกบ่อยแค่ไหน

  4. Table มีกี่ Rows

  5. Query คืนกี่ Rows

  6. ใช้ WHERE อะไร

  7. ใช้ JOIN อะไร

  8. ใช้ ORDER BY อะไร

  9. ใช้ LIMIT หรือไม่

  10. มี Existing Index อะไร

  11. มี Redundant Index หรือไม่

  12. ใช้ SHOW INDEX

  13. ใช้ EXPLAIN

  14. ดู Plan ก่อนเพิ่ม Index

  15. เก็บ Query Timing Baseline

  16. ตรวจ Single-column Index

  17. ตรวจ Composite Index

  18. ตรวจ Column Order

  19. ตรวจ Selectivity

  20. ตรวจ Foreign Key Index

  21. ไม่ Index ทุก Column

  22. ไม่สร้าง Covering Index ทุก Query

  23. ระวัง Write Performance

  24. ตรวจ INSERT Performance

  25. ตรวจ UPDATE Performance

  26. ตรวจ DELETE Performance

  27. ใช้ mysql_debug

  28. ใช้ oxmysql Debug UI เมื่อเหมาะสม

  29. ใช้ FiveM Profiler

  30. ตรวจ Server Hitch

  31. ตรวจ Database CPU

  32. ทดสอบด้วย Production-like Data

  33. Backup ก่อน Schema Change

  34. Test บน Staging

  35. EXPLAIN หลังเพิ่ม Index

  36. Benchmark หลังเพิ่ม Index

  37. ตรวจ Query Count

  38. แก้ N+1 Query

  39. ลด SELECT *

  40. ใช้ Pagination

  41. Cache เมื่อเหมาะสม

  42. ไม่ Query ทุก Frame

  43. ใช้ Prepare เมื่อ Query ถูกเรียกบ่อยและเหมาะสม

  44. ANALYZE TABLE เมื่อมีเหตุผลด้าน Statistics

  45. อย่าลบ Index โดยไม่ตรวจ Workload

ตารางคำสั่ง Database Optimization ที่ควรรู้

คำสั่งหน้าที่
SHOW INDEX FROM tableดู Index ที่มี
EXPLAIN SELECT ...ดู Execution Plan
CREATE INDEXเพิ่ม Regular Index
CREATE UNIQUE INDEXเพิ่ม Unique Index
ANALYZE TABLEอัปเดต Statistics สำหรับ Optimizer
SHOW INDEX_STATISTICSดู Index Usage Statistics ใน Environment ที่รองรับ
mysql_debugดู oxmysql Query Timing
FiveM Profilerหา Resource/Thread ที่ Hitch

MariaDB มีเครื่องมือ Index, EXPLAIN, ANALYZE TABLE และ Index Statistics โดยตรง ส่วน oxmysql และ FiveM Profilerช่วยเชื่อม Database Performance กลับมาที่ Resource.

FiveM MySQL Index ช่วยอะไร

ช่วยให้ Database Optimizer มีโครงสร้างเพิ่มเติมสำหรับค้นหา Rows ตาม Query Pattern ที่เหมาะสม เช่น:

WHERE `owner` = ?

แทนการพึ่ง Table Scan ในทุกสถานการณ์

MariaDB มี Index Optimization Documentation โดยตรงสำหรับการออกแบบ Index ตาม Query.

FiveM Query ไม่มี Index แก้อย่างไร

อย่าเริ่มด้วย CREATE INDEX ทันที

ทำ:

Query จริง
↓
EXPLAIN
↓
SHOW INDEX
↓
วิเคราะห์ WHERE/JOIN/ORDER BY
↓
สร้าง Index ใน Test DB
↓
EXPLAIN ใหม่
↓
Benchmark

FiveM EXPLAIN ใช้อย่างไร

ตัวอย่าง:

EXPLAIN
SELECT
    `id`,
    `model`
FROM `vehicles`
WHERE `owner` = 'license:example';

MariaDB ระบุว่า EXPLAIN แสดงข้อมูลเกี่ยวกับวิธี Execute Query.

FiveM Composite Index คืออะไร

คือ Index หลาย Columns เช่น:

CREATE INDEX `idx_vehicles_owner_stored`
ON `vehicles` (`owner`, `stored`);

MariaDB เรียกว่า Compound/Composite Index.

FiveM Query ช้าหลังข้อมูลเยอะขึ้น

ตรวจ:

Table Size
↓
EXPLAIN
↓
Rows Examined
↓
Index
↓
Query Count
↓
Result Size

เพราะ Query ที่ทำงานเร็วกับ Data ขนาดเล็กอาจมี Scaling Characteristics ต่างเมื่อข้อมูลโตขึ้น

FiveM Index เยอะเกินไปมีผลไหม

มี

MariaDB ระบุว่า Index ทุกตัวต้องได้รับการ Update เมื่อ Insert และ Index จำนวนมากทำให้ Insert ช้าลง.

จึงต้อง Balance:

Read Performance
กับ
Write Performance

FiveM ควร Index identifier ไหม

ถ้า Queries หลักของ Table ใช้:

WHERE `identifier` = ?

บ่อยมาก ก็ควรวิเคราะห์ Index บน Column นี้

แต่ต้องตรวจ Existing Index และ EXPLAIN ก่อน

FiveM ควร Index stored ไหม

ถ้า stored มีเพียง:

0
1

Single-column Index อาจไม่ได้มีประโยชน์มากในหลาย Data Distributions

แต่ Composite Index:

(owner, stored)

อาจมีประโยชน์กับ Query ที่ Filter Owner ก่อน

ต้องวัดด้วย EXPLAIN

FiveM ควร Index created_at ไหม

ขึ้นกับ Queries

ถ้ามี:

WHERE identifier = ?
ORDER BY created_at DESC

อาจพิจารณา Composite Index ตาม Query Pattern

แต่ถ้า created_at ไม่เคยใช้ Filter/Order การสร้าง Index เพียงเพราะมี Column นี้ก็อาจไม่จำเป็น

FiveM เพิ่ม Index แล้ว Restart Server ไหม

Index เป็น Database Schema Object ไม่ได้เป็น FiveM Resource Code

หลัง CREATE INDEX สำเร็จ Database สามารถใช้ Index ตาม Optimizer ได้

อย่างไรก็ตาม Resource Query Behavior และ Connection State ควรถูกทดสอบตาม Environment จริง ไม่ควร Restart Production Server โดยไม่จำเป็นเพียงเพื่อหวังว่า Index จะเริ่มทำงาน

FiveM Index หายหลัง Restart ไหม

Index เป็นส่วนของ Database Schema จึงควรคงอยู่หลัง FiveM Resource/FXServer Restart ตราบใดที่ Database Schema ไม่ถูกเปลี่ยนหรือลบ

ต่างจาก Runtime Data เช่น Entity Handle หรือ Cache

FiveM Index ทำให้ oxmysql เร็วขึ้นไหม

oxmysql เป็น Wrapper ที่ส่ง Query ไปยัง Database

ถ้า Database Query ได้ประโยชน์จาก Index Response Time ที่ oxmysqlได้รับก็สามารถดีขึ้นตาม Database Execution

แต่ oxmysql เองเตือนว่า Query Speed ยังขึ้นกับ Hardware, Database Settings, Version และ Workload.

FAQ FiveM MySQL Index

FiveM MySQL Index คืออะไร

คือ Database Index ที่ MySQL/MariaDB สามารถใช้เพื่อช่วยค้นหา Records ตาม Query Pattern ที่เหมาะสม โดย MariaDB รองรับ Primary, Unique และ Regular Indexes.

EXPLAIN คืออะไร

เป็นคำสั่งสำหรับดูข้อมูลว่า MariaDB วางแผน Execute SELECT, UPDATE หรือ DELETE อย่างไร.

Composite Index คืออะไร

คือ Index ที่มีหลาย Columns เช่น INDEX(owner, stored).

Index เยอะยิ่งดีไหม

ไม่ MariaDB ระบุว่า Index เพิ่มต้นทุนของ Writes และ Redundant Indexes อาจไม่จำเป็น.

INDEX(owner) กับ INDEX(owner, stored) ต้องมีทั้งคู่ไหม

ไม่จำเป็นเสมอไป เพราะ MariaDB ระบุว่า INDEX(a,b) สามารถรองรับ Prefix a ได้ใน Query Pattern ที่เหมาะสม.

ANALYZE TABLE คืออะไร

ใช้วิเคราะห์และอัปเดต Key Distribution/Statistics ที่ Optimizer ใช้ตัดสิน Execution Plan.

FiveM Slow Query ต้องเพิ่ม Index ทุกครั้งไหม

ไม่ ต้องตรวจ EXPLAIN, Query Frequency, Table Size, Result Size และ Resource Code ก่อน เพราะปัญหาอาจไม่ได้มาจาก Index

MySQL.prepare แทน Index ได้ไหม

ไม่ได้ Prepare ช่วย Frequently-called Queries ใน oxmysql แต่ Index เป็น Database Structure สำหรับ Query Optimization คนละ Layer.

Index ช่วย Server Hitch ได้ไหม

หากต้นเหตุคือ SQL Query ที่ช้าเพราะ Database Access Pattern การ Optimize Query/Index อาจช่วยได้ แต่ Cfx.re ระบุว่า Hitch ยังเกิดได้จากปัญหาอื่น เช่น Unoptimized Loops เช่นกัน.

จะรู้ได้อย่างไรว่า Index ช่วยจริง

เปรียบเทียบ:

EXPLAIN ก่อน
Query Timing ก่อน

vs

EXPLAIN หลัง
Query Timing หลัง

ด้วย Data และ Workload ใกล้ Production

ประเด็นสำคัญ

FiveM MySQL/MariaDB Index ไม่ควรถูกสร้างด้วยแนวคิด:

Query ช้า
=
เพิ่ม Index

แต่ควรใช้กระบวนการ:

Query ช้า
↓
mysql_debug
↓
EXPLAIN
↓
SHOW INDEX
↓
ดู WHERE/JOIN/ORDER BY
↓
ออกแบบ Single/Composite Index
↓
EXPLAIN ใหม่
↓
Benchmark
↓
Profiler

MariaDB มี EXPLAIN สำหรับดู Execution Plan และมีทั้ง Single-column, Composite, Covering และ Index Statistics ที่ช่วยในการ Query Optimization.

สิ่งที่ต้องระวังคือ Index ไม่ใช่ของฟรี เพราะ Index ทุกตัวเพิ่มงานให้ Write Operations และ Index ที่ซ้ำซ้อนอาจไม่จำเป็น ดังนั้นอย่า Index ทุก Column หรือสร้าง Index ใหม่ทุกครั้งที่เห็น Slow Query Warning.

สำหรับ FiveM ให้ใช้ oxmysql Debug Timing ร่วมกับ FiveM Profiler เพราะ Cfx.re ระบุว่า SQL Query ที่ใช้เวลานานสามารถทำให้เกิด Hitch Warning ได้ แต่ Profiler ยังช่วยแยกได้ว่าปัญหาอยู่ใน Database หรือ Resource Code ส่วนอื่น.

สำหรับผู้อ่าน comsiam ให้จำสูตร “Slow Query → EXPLAIN → Index → Measure” และ comsiam แนะนำว่าอย่าดูเพียงว่า Query ใช้ Index หรือไม่ แต่ให้ดูทั้ง Query Time, Query Count, Rows, Player Count และ Write Performance ด้วย เพราะเป้าหมายสุดท้ายไม่ใช่มี Index เยอะที่สุด แต่คือให้ Database ทำงานได้เหมาะกับ FiveM Workload จริง

Comments

Popular posts from this blog

FiveM ยังน่าเล่นไหม? Enhanced เปลี่ยน FiveM แค่ไหน

FiveM คืออะไร เล่นอย่างไร สำหรับมือใหม่ เริ่มต้นตั้งแต่ศูนย์

วิธีตั้ง Admin Permission ด้วย add_ace และ add_principal FiveM แบบละเอียด