ระบบไม่ได้ทำงานหนักกับข้อมูลทุกส่วน แต่งานส่วนใหญ่กระจุกอยู่เพียงสองจุด
อาการที่เห็นจากภายนอกคือระบบตอบสนองช้ากว่าที่ผู้ใช้คาดหวัง แต่ความช้าเพียงอย่างเดียวยังไม่บอกว่าเกิดจาก Application, คำสั่งเรียกข้อมูล, Database หรือ Storage (ระบบจัดเก็บข้อมูล เช่น Disk) ทีมจึงใช้ AWR เพื่อดูว่าฐานข้อมูลใช้ทรัพยากรไปกับงานส่วนใดมากที่สุด
AWR พบ Logical Reads รวมประมาณ 707.23 ล้านครั้งในช่วงรายงาน แต่ 628.87 ล้านครั้ง หรือ 88.92% กระจุกอยู่ที่ Table (ตารางข้อมูล) เพียงรายการเดียว และอีก 38.71 ล้านครั้ง หรือ 5.47% อยู่ที่ Partition หนึ่งของอีก Table
สองจุดนี้รวมกันคิดเป็น 94.39% ของ Logical Reads ทั้งหมด ภาพจึงไม่ใช่ว่าฐานข้อมูลทำงานหนักกับทุกส่วนเท่า ๆ กัน แต่เหมือนพนักงานใช้เวลาส่วนใหญ่ เปิดแฟ้มเพียงสองแฟ้มซ้ำไปมา ถ้าแฟ้มนั้นอยู่บนโต๊ะก็ไม่ต้องเดินไปห้องเก็บเอกสาร แต่การเปิดหน้าเดิมหลายร้อยล้านครั้งยังใช้เวลาและกำลังประมวลผล
ตัวเลขระดับ Segment (พื้นที่จัดเก็บของ Table, Index ซึ่งเป็นโครงสร้างช่วยค้นข้อมูล หรือ Partition) บอกว่า “อ่านที่ไหน” แต่ยังไม่บอกว่า SQL ใดเป็นผู้สั่งอ่าน อ่านเพราะเงื่อนไขอะไร หรือ Execution Plan (แผนที่ Oracle เลือกใช้ค้นข้อมูล) เลือกเส้นทางแบบใด
Logical Read ไม่เท่ากับการอ่าน Disk ทุกครั้ง Oracle จะมองหา Data Block ใน Buffer Cache (พื้นที่หน่วยความจำที่เก็บ Block ซึ่งเคยถูกใช้งาน) ก่อน หากพบก็อ่านจาก Memory ได้ แต่การตรวจ Block, ประมวลผลเงื่อนไข และอ่านซ้ำ ยังสร้างภาระ CPU และงานภายในฐานข้อมูล
อยากเข้าใจศัพท์ให้ลึกขึ้น?
อ่านต่อได้ที่ Logical Reads ต่างจาก Physical Reads อย่างไร, จาก Segment ไปหา SQL ได้อย่างไร และ Partition Pruning ช่วยอะไร
จาก Object ที่ถูกอ่านมาก ไปหา SQL ที่ทำให้เกิดงานนั้น
Segment Statistics บอก “ที่ไหน” ก่อน
Segment คือพื้นที่จัดเก็บของ Table, Index หรือ Partition ภายใน Oracle ส่วน Segment Statistics ใน AWR ช่วยจัดอันดับว่า Segment ใดมี Logical Reads สูง ทีมจึงจำกัดวงจากทั้งฐานข้อมูลเหลือ Object เพียงไม่กี่รายการ โดยไม่ต้องเดาจากขนาด Table
Object ที่ถูกอ่านมากยังไม่ใช่ Root Cause
Table ไม่ได้อ่านตัวเอง ทีมต้องเชื่อม Segment กับ SQL ordered by Gets/Reads แล้วดู Execution Plan (แผนที่ Oracle ใช้เลือกวิธีค้นข้อมูล), Predicate (เงื่อนไขค้นหา), Bind Value และจำนวนครั้งที่ SQL ถูกเรียก เพื่อแยกว่าเกิดจาก SQL ที่ถูกเรียกถี่ อ่าน Block ต่อครั้งมาก หรือเกิดทั้งสองอย่างพร้อมกัน
Partition และ Index ต้องสัมพันธ์กับวิธีที่ Application ค้นข้อมูล
Partition คือการแบ่ง Table ใหญ่ออกเป็นส่วนย่อย เช่น แบ่งตามเดือนหรือไตรมาส หากเงื่อนไข SQL ระบุ Partition Key ได้ Oracle อาจใช้ Partition Pruning (ตัด Partition ที่ไม่เกี่ยวข้องออกจากการค้นหา) แต่ถ้าเงื่อนไขไม่สัมพันธ์กัน การมี Partition อยู่แล้วก็ไม่ได้รับประกันว่าจะอ่านข้อมูลน้อยลง
ทีมจึงพิจารณา Local Index, Global Index และวงจรชีวิตข้อมูลร่วมกับ Predicate, ความถี่ของ DML, Unique Constraint และวิธี Archive ข้อมูลเก่า ไม่เลือก Index จากชื่อประเภทเพียงอย่างเดียว
ทีมแก้ 3 จุด: Index, วิธีเข้าถึง Partition และการจัดการข้อมูลเก่า
หลังเชื่อม Object ที่มีการอ่านสูงเข้ากับ SQL และ Execution Plan ได้แล้ว ทีมไม่ได้หยุดอยู่ที่รายงาน แต่ปรับวิธีที่ Oracle ค้นหาและดูแลข้อมูลให้ตรงกับงานจริง
- ปรับ Index ให้ตรงกับวิธีค้นหาของ SQL: เลือกโครงสร้าง Index จากเงื่อนไขค้นหาและรูปแบบการใช้งานจริง เพื่อให้ Oracle เข้าถึงข้อมูลที่ต้องใช้โดยไม่ต้องเปิดดูข้อมูลกว้างเกินไป
- ปรับวิธีเข้าถึง Partition: ทำให้เงื่อนไขของ SQL สอดคล้องกับการแบ่งข้อมูล เพื่อให้ Oracle เลือกอ่านเฉพาะ Partition ที่เกี่ยวข้องแทนการแตะข้อมูลหลายส่วนเกินความจำเป็น
- จัดการ Data Lifecycle (วงจรชีวิตข้อมูล): วางวิธีดูแลและแยกข้อมูลเก่าตามช่วงเวลาที่ต้องใช้งาน เพื่อลดปริมาณข้อมูลที่งานประจำต้องค้นหาและดูแล
หลังแก้ ระบบตอบสนองดีขึ้น
Oracle ใช้เส้นทางค้นข้อมูลที่ตรงกับงานมากขึ้น และข้อมูลที่งานประจำต้องดูแลมีขอบเขตเหมาะสมขึ้น จึงลดการทำงานที่ไม่จำเป็นในจุดซึ่งเคยมี Logical Reads กระจุกตัวสูง
เปิดดู Logical I/O, Segment Statistics และการเลือก Index
รายละเอียดส่วนนี้เก็บศัพท์ Oracle และตัวเลขสำหรับ DBA/IT และการค้นหา แต่พับไว้เพื่อให้เรื่องหลักอ่านต่อเนื่อง
Logical Reads ต่างจาก Physical Reads อย่างไร
Logical Reads หรือ Buffer Gets คือจำนวนครั้งที่ Oracle เข้าถึง Database Block ผ่าน Buffer Cache หาก Block อยู่ใน Cache แล้ว Oracle ใช้งานได้โดยไม่ต้องอ่านจาก Storage หากไม่อยู่จึงอาจเกิด Physical Read เพื่อนำ Block เข้ามา
Logical Reads สูงไม่ได้หมายความว่า Storage ช้าโดยตรง แต่สะท้อนปริมาณ Block access ซึ่งสัมพันธ์กับ CPU, Latch/Mutex และประสิทธิภาพของ SQL ได้ การอ่านค่าจึงต้องดู Executions, Gets per Execution, Rows processed และ Execution Plan ร่วมกัน
หลักฐานจาก AWR Segment Statistics
ตัวเลขด้านล่างเป็นยอดรวมจาก AWR ช่วงแรกประมาณ 6 ชั่วโมง ชื่อ Schema, Object และ Partition ถูกแทนด้วยชื่อทั่วไป
| Segment | ประเภท | Logical Reads | % Total |
|---|---|---|---|
[TABLE_A] |
Table | 628,870,000 | 88.92% |
[TABLE_B] |
Table Partition | 38,705,328 | 5.47% |
| สอง Segment รวมกัน | — | 667,575,328 | 94.39% |
| Logical Reads ทั้งระบบ | — | 707,229,497 | 100% |
Segment Statistics บอก Object แต่จะหา SQL ต้นทางอย่างไร
Segment Statistics แสดงว่า Block access กระจุกอยู่ที่ Object ใด แต่ไม่ได้ผูกทุก Logical Read เข้ากับ SQL โดยตรง ทีมจึงใช้ SQL ordered by Gets/Reads, ASH หรือ SQL statistics ในช่วงเวลาเดียวกันเพื่อจำกัด SQL ที่เกี่ยวข้อง แล้วตรวจ Execution Plan และ Predicate ต่อ
การเห็น Table ในแผนไม่ได้แปลว่าเป็น Full Table Scan เสมอ ต้องอ่าน Operation, Access/Filter Predicate, Cardinality, Starts, Buffers และจำนวน Execution ร่วมกัน
Partition Pruning, PSTART และ PSTOP บอกอะไร
Partition Pruning คือการที่ Optimizer ตัด Partition ซึ่งไม่เกี่ยวข้องกับ Predicate ออกจากการค้นหา ใน Execution Plan ค่า PSTART และ PSTOP ช่วยแสดงขอบเขต Partition ที่ถูกเข้าถึง
Pruning ขึ้นกับ Partition Key, Predicate, Data Type และวิธีใช้ Bind/Function การเปลี่ยน Index เป็น LOCAL เพียงอย่างเดียวไม่ได้รับประกันว่า Table Partition จะถูก Prune
Local Index กับ Global Index เลือกอย่างไร
Local Index แบ่ง Index ให้สอดคล้องกับ Table Partition จึงสะดวกต่อ Partition maintenance ส่วน Global Index ครอบคลุมข้อมูลข้าม Partition และอาจเหมาะกับ Query หรือ Unique Constraint บางรูปแบบ
การเลือกต้องดู Leading Columns, Predicate, Selectivity, DML cost, Uniqueness และขั้นตอน Archive/Drop Partition ไม่มีกฎว่า Local Index เร็วกว่าหรือเหมาะกับทุก Query
Archive และ Drop Partition ต้องพิจารณาอะไร
การย้ายข้อมูลเก่าออกช่วยลดปริมาณข้อมูลที่ระบบต้องดูแลและทำให้ Partition maintenance เป็นระบบ แต่ต้องกำหนด Retention, เจ้าของข้อมูล, Backup/Recovery, การค้นย้อนหลัง และแผนย้อนกลับก่อนดำเนินการ
ที่มาของตัวเลขและคำอธิบายทางเทคนิค
- หลักฐาน Case: AWR และ AWR Compare ที่จัดทำจากระบบจริง โดยเผยแพร่เฉพาะตัวเลขสรุปซึ่งไม่ระบุองค์กรหรือ Object
- การปกปิดข้อมูล: ไม่เผยแพร่ชื่อองค์กร, Hostname, Schema, Table, Partition, SQL ID, SQL Text หรือข้อมูลภายใน
- Partition Pruning: อ้างอิง Oracle Database VLDB and Partitioning Guide
- Partitioned Index: อ้างอิง Oracle Database VLDB and Partitioning Guide: Index Partitioning
AWR ชี้ว่า Logical Reads กระจุกอยู่ที่ Object เพียงไม่กี่รายการหรือไม่?
ทีม VT Technology ช่วยเชื่อม Segment, SQL, Execution Plan, Index และ Partition เพื่อหาว่าฐานข้อมูลกำลังอ่านข้อมูลมากเพราะอะไร และเลือกจุดแก้ให้ตรงกับ Workload จริง
ปรึกษาการวิเคราะห์ Oracle Performance