แคชแบบสอบถามเป็นคุณลักษณะที่ดีมาก แต่อย่าถูกล่อลวงให้ใส่ใจมากเกินไปและอย่าล่อลวงให้มีขนาดใหญ่เกินไป การทำความเข้าใจกับเรื่องภายในนั้นอาจช่วยในเรื่องนั้นได้
แคชคิวรีเริ่มต้นจากการเป็นหนึ่งหน่วยความจำที่มีขนาดใหญ่ต่อเนื่องกัน จากนั้น "บล็อก" ถูกแกะสลักจากบล็อกขนาดใหญ่นี้:
- แบบสอบถามที่แคชแต่ละรายการจะบล็อก
- ชุดผลลัพธ์ของสหายจะใช้เวลาบล็อก
- แต่ละตารางที่อ้างอิงโดยแบบสอบถามที่แคชใด ๆ (ไม่ว่าจะมีคิวรีจำนวนเท่าใดที่อ้างอิงถึงตารางนั้นในแคช) ก็ใช้บล็อกหนึ่งรายการต่อตาราง
ขนาดบล็อกเป็นแบบไดนามิก แต่เซิร์ฟเวอร์จะจัดสรรอย่างน้อยquery_cache_min_res_unit
ไบต์ต่อบล็อกโดยมีค่าเริ่มต้นโดยทั่วไปคือ 4096 ไบต์
เมื่อใดก็ตามที่แบบสอบถามผลลัพธ์ที่แนบมาและการอ้างอิงตารางจะถูกลบออกจากแคชไม่ว่าจะด้วยการทำให้ข้อมูลในตารางมีการเปลี่ยนแปลงหรือโดยการตัดเพื่อทำให้มีที่ว่างสำหรับการสืบค้นที่ใหม่กว่า จำนวนของ "บล็อกฟรี" มักจะเพิ่มขึ้น ... แม้ว่าจะมีบล็อกที่ต่อเนื่องกันตั้งแต่สองบล็อกขึ้นไป แต่จำนวนของ "บล็อกฟรี" จะเพิ่มขึ้น 1 ครั้งเท่านั้นและ "บล็อกฟรี" จะไม่เพิ่มขึ้นหากใหม่ บล็อกที่ว่างจะต่อเนื่องกับบล็อกที่ว่างอยู่แล้ว - ขนาดของบล็อกที่ว่างนั้นจะใหญ่ขึ้น บล็อกที่เปิดของหน่วยความจำว่างในแคชแบบสอบถามจะถูกนับเป็น 1 บล็อกว่าง
แน่นอนบล็อกฟรีขนาดเล็กกว่าquery_cache_min_res_unit
จะไม่ถูกใช้เลย
ดังนั้นเคียวรีแคชแฟรกเมนต์ ถ้าเซิร์ฟเวอร์ที่ต้องการแคชแบบสอบถามใหม่และไม่มีการบล็อกฟรีมีขนาดเพียงพอสามารถจัด (นั่นคือคำอธิบายง่าย deceptively เพราะขั้นตอนวิธีพื้นฐานที่มีความซับซ้อน) อย่างอื่นจะต้องมีการตัดแต่ง ... Qcache_lowmem_prunes
ที่ของคุณ มีอัลกอริทึม "น้อยที่สุดเมื่อเร็ว ๆ นี้" (LRU) ที่ใช้ตัดสินใจสิ่งที่ถูกตัด
มันจะสมเหตุสมผลถ้าถามว่าทำไมเซิร์ฟเวอร์ถึงไม่จัดเรียงข้อมูลในหน่วยความจำ ... แต่นั่นก็ไม่สมเหตุสมผล แคชแบบสอบถามช่วยได้ แต่ก็ไม่ได้เป็นกลยุทธ์ คุณไม่ต้องการลงทุนเวลาประมวลผล (โดยเฉพาะเวลาที่ใช้ในล็อกส่วนกลาง) กับงานบำรุงรักษาที่ไม่จำเป็น
มันจะเป็นการต่อต้านสำหรับเซิร์ฟเวอร์ที่จะใช้เวลาในการจัดเรียงใหม่ - จัดเรียงข้อมูล - หน่วยความจำในแคชแบบสอบถามเนื่องจากผลลัพธ์ที่แคชจะเปลี่ยนแปลงตลอดเวลาและจุดทั้งหมดของแคชคือการปรับปรุงประสิทธิภาพ
การล็อกส่วนกลางเป็นเหตุผลที่ดีมากที่คุณไม่ต้องการใช้แคชคิวรีที่มีขนาดใหญ่เกินไป ... เซิร์ฟเวอร์จะใช้เวลามากเกินไปเนื่องจากคิวรอคอยคิวเพื่อดูว่าแคชนั้นเกิดขึ้นหรือไม่และประสิทธิภาพของคุณจะแย่ลง .
แต่qcache_free_blocks
สิ่งสำคัญคือตัวบ่งชี้การกระจายตัวของพื้นที่ว่าง นั่นคือตอนนี้มีบล็อกที่ไม่ต่อเนื่องกันจำนวนมากของหน่วยความจำที่มีอยู่ในแคชแบบสอบถาม สำหรับการแทรกแบบสอบถามใหม่ลงในแคชจะต้องมีพื้นที่ว่างมากพอที่จะมีแบบสอบถามผลลัพธ์และ (บางครั้ง) อ้างอิงตารางของ ถ้าไม่มีก็ต้องไปอย่างอื่น ... ซึ่งเป็นสิ่งที่คุณเห็น โปรดทราบอีกครั้งว่าพื้นที่ว่างไม่จำเป็นต้องต่อเนื่องกันเสมอไป (จากสิ่งที่ฉันสามารถบอกได้ด้วยการอ่านซอร์สโค้ด) แต่ไม่ทุกหลุมจะเต็มเมื่อมีการแตกแฟรกเมนต์
แต่การแตกแฟรกเมนต์มีแนวโน้มที่จะลดลงเมื่อเวลาผ่านไปสำหรับปริมาณงานที่กำหนดเนื่องจากมักจะไม่มีสิ่งใดอยู่ในแคชคิวรีตราบใดที่คุณอาจคาดหวัง
นี่เป็นเพราะในบางวิธีแคชแบบสอบถามนั้นยอดเยี่ยมในความเรียบง่าย
เมื่อใดก็ตามที่ข้อมูลในตารางที่อ้างถึงโดยการเปลี่ยนแปลงแบบสอบถามที่เก็บไว้แบบสอบถามทั้งหมดที่เกี่ยวข้องกับตารางนั้นจะถูกลบออกจากแคช - แม้ว่าการเปลี่ยนแปลงจะไม่ส่งผลกระทบต่อผลการแคช สิ่งนี้จะเป็นจริงหากตารางมีการเปลี่ยนแปลง แต่จะไม่เปลี่ยนแปลงดังเช่นในกรณีของธุรกรรม InnoDB ที่ย้อนกลับ รายการแคชแบบสอบถามที่อ้างอิงถึงตารางนั้นถูกลบทิ้งไปแล้ว
นอกจากนี้แคชแบบสอบถามจะถูกตรวจสอบสำหรับคิวรีขาเข้าแต่ละรายการก่อนที่เซิร์ฟเวอร์จะแยกวิเคราะห์คิวรีจริง สิ่งเดียวที่จะจับคู่คือแบบสอบถามอื่นที่แม่นยำเหมือนกันไบต์ต่อไบต์ SELECT * FROM my_table
และselect * from my_table
ไม่เหมือนกันไบต์ต่อไบต์ดังนั้นแคชแบบสอบถามไม่ทราบว่าเป็นคิวรี่เดียวกัน
FLUSH QUERY CACHE
ไม่ล้างแคชแบบสอบถาม มันจัดระเบียบแคชแบบสอบถามซึ่งเป็นสาเหตุที่Qcache_free_blocks
กลายเป็น "1" พื้นที่ว่างทั้งหมดถูกรวมเข้าด้วยกัน
RESET QUERY CACHE
จริง ๆ แล้วจะล้างออก (ล้างเนื้อหาทั้งหมดของ) แคชแบบสอบถาม
FLUSH STATUS
ล้างนับ SHOW STATUS
แต่นี้เป็นสิ่งที่คุณไม่ต้องการที่จะทำประจำเพราะเลขนี้ออกมามากที่สุดของตัวแปรสถานะ
นี่คือการสาธิตอย่างรวดเร็ว
พื้นฐาน:
mysql> show status like '%qcache%';
+-------------------------+----------+
| Variable_name | Value |
+-------------------------+----------+
| Qcache_free_blocks | 1 |
| Qcache_free_memory | 67091120 |
| Qcache_hits | 0 |
| Qcache_inserts | 0 |
| Qcache_lowmem_prunes | 0 |
| Qcache_not_cached | 1 |
| Qcache_queries_in_cache | 0 |
| Qcache_total_blocks | 1 |
+-------------------------+----------+
เรียกใช้แบบสอบถาม ...
mysql> select * from junk where id = 2;
บล็อกทั้งหมดเพิ่มขึ้น 3 แทรกโดย 1 และแบบสอบถามในแคชคือ 1
+-------------------------+----------+
| Variable_name | Value |
+-------------------------+----------+
| Qcache_free_blocks | 1 |
| Qcache_free_memory | 67089584 |
| Qcache_inserts | 1 |
| Qcache_queries_in_cache | 1 |
| Qcache_total_blocks | 4 |
+-------------------------+----------+
เรียกใช้ข้อความค้นหาเดียวกัน แต่ใช้ตัวพิมพ์ใหญ่ต่างกัน ...
mysql> SELECT * FROM junk where id = 2;
แบบสอบถามนี้ถูกแคชแยกจากกัน บล็อกทั้งหมดเพิ่มขึ้นเพียง 2 เพราะเรามีบล็อกที่จัดสรรไว้สำหรับตารางแล้ว
+-------------------------+----------+
| Variable_name | Value |
+-------------------------+----------+
| Qcache_free_blocks | 1 |
| Qcache_free_memory | 67088560 |
| Qcache_inserts | 2 |
| Qcache_queries_in_cache | 2 |
| Qcache_total_blocks | 6 |
+-------------------------+----------+
ตอนนี้เราเปลี่ยนที่แตกต่างกันแถวในตาราง
mysql> update junk set things = 'items' where id = 1;
ทั้งแบบสอบถามและการอ้างอิงตารางนั้นไม่ถูกต้องจากแคชทำให้เรามีบล็อกว่างที่ต่อเนื่องกัน 1 บล็อกหน่วยความจำแคชทั้งหมดเป็นอิสระและพื้นที่ว่างทั้งหมดรวมอยู่ในบล็อกเดียว
+-------------------------+----------+
| Variable_name | Value |
+-------------------------+----------+
| Qcache_free_blocks | 1 |
| Qcache_free_memory | 67091120 |
| Qcache_queries_in_cache | 0 |
| Qcache_total_blocks | 1 |
+-------------------------+----------+
MySQL จะไม่เก็บแบบสอบถามไว้ในแคชที่ไม่ได้กำหนดไว้เช่นSELECT NOW();
หรือแบบสอบถามใด ๆ ที่คุณบอกว่าไม่ให้แคชโดยเฉพาะ SELECT SQL_NO_CACHE ...
เป็นคำสั่งที่บอกเซิร์ฟเวอร์ไม่ให้เก็บผลลัพธ์ไว้ในแคช มันมีประโยชน์สำหรับการเปรียบเทียบเวลาดำเนินการจริงของคิวรีเมื่อแคชให้การตอบสนองที่รวดเร็วในการดำเนินการที่ตามมา