การเพิ่มประสิทธิภาพการสืบค้น PostgreSQL เป็นกลุ่ม คิริลล์ โบโรวิคอฟ (เทนเซอร์)

รายงานนำเสนอแนวทางบางประการที่เอื้ออำนวย ตรวจสอบประสิทธิภาพของคำสั่ง SQL เมื่อมีคำสั่งหลายล้านคำสั่งต่อวันและมีเซิร์ฟเวอร์ PostgreSQL ที่ได้รับการตรวจสอบหลายร้อยรายการ

โซลูชันทางเทคนิคใดที่ช่วยให้เราสามารถประมวลผลข้อมูลปริมาณมากได้อย่างมีประสิทธิภาพ และสิ่งนี้ทำให้ชีวิตของนักพัฒนาทั่วไปง่ายขึ้นได้อย่างไร


ใครสนใจบ้าง? การวิเคราะห์ปัญหาเฉพาะและเทคนิคการปรับให้เหมาะสมต่างๆ การสืบค้น SQL และการแก้ปัญหา DBA ทั่วไปใน PostgreSQL คุณก็สามารถทำได้เช่นกัน อ่านบทความชุดหนึ่ง ในหัวข้อนี้

การเพิ่มประสิทธิภาพการสืบค้น PostgreSQL เป็นกลุ่ม คิริลล์ โบโรวิคอฟ (เทนเซอร์)
ฉันชื่อ Kirill Borovikov ฉันเป็นตัวแทน บริษัทเทนเซอร์. โดยเฉพาะฉันมีความเชี่ยวชาญในการทำงานกับฐานข้อมูลในบริษัทของเรา

วันนี้ฉันจะบอกคุณว่าเราเพิ่มประสิทธิภาพการสืบค้นอย่างไร ในเมื่อคุณไม่จำเป็นต้อง "แยก" ประสิทธิภาพของคำค้นหาเดียว แต่แก้ปัญหาได้ทั้งหมด เมื่อมีคำขอเป็นล้านคำขอ และคุณจำเป็นต้องค้นหาบางส่วน แนวทางการแก้ปัญหา ปัญหาใหญ่นี้

โดยทั่วไปแล้ว Tensor สำหรับลูกค้าของเรานับล้านคนคือ VLSI คือแอปพลิเคชันของเรา: โซเชียลเน็ตเวิร์กองค์กร, โซลูชั่นสำหรับการสื่อสารผ่านวิดีโอ, สำหรับการไหลของเอกสารภายในและภายนอก, ระบบบัญชีสำหรับการบัญชีและคลังสินค้า,... นั่นคือ "เมกะคอมไบน์" สำหรับการจัดการธุรกิจแบบครบวงจรซึ่งมีมากกว่า 100 รูปแบบที่แตกต่างกัน โครงการภายใน

เพื่อให้มั่นใจว่าทั้งหมดทำงานและพัฒนาได้ตามปกติ เรามีศูนย์พัฒนา 10 แห่งทั่วประเทศ และยังมีอีกหลายแห่งในนั้น นักพัฒนา 1000 คน.

เราทำงานร่วมกับ PostgreSQL มาตั้งแต่ปี 2008 และได้สั่งสมสิ่งที่เราประมวลผลไว้จำนวนมาก เช่น ข้อมูลลูกค้า สถิติ การวิเคราะห์ ข้อมูลจากระบบข้อมูลภายนอก - มากกว่า 400TB. เพียงอย่างเดียวมีเซิร์ฟเวอร์ที่ใช้งานจริงประมาณ 250 เครื่อง และโดยรวมแล้วมีเซิร์ฟเวอร์ฐานข้อมูลประมาณ 1000 เครื่องที่เราตรวจสอบ

การเพิ่มประสิทธิภาพการสืบค้น PostgreSQL เป็นกลุ่ม คิริลล์ โบโรวิคอฟ (เทนเซอร์)

SQL เป็นภาษาประกาศ คุณไม่ได้อธิบายว่าบางสิ่งควรทำงาน “อย่างไร” แต่อธิบายว่าคุณต้องการบรรลุ “อะไร” DBMS รู้ดีกว่าวิธีการเข้าร่วม - วิธีเชื่อมต่อตารางของคุณ เงื่อนไขใดที่ต้องกำหนด อะไรจะผ่านดัชนี อะไรจะไม่...

DBMS บางตัวยอมรับคำแนะนำ: "ไม่ เชื่อมต่อทั้งสองตารางนี้ในคิวดังกล่าว" แต่ PostgreSQL ไม่สามารถทำได้ นี่คือจุดยืนที่ใส่ใจของนักพัฒนาชั้นนำ: “เราอยากจะใช้เครื่องมือเพิ่มประสิทธิภาพการสืบค้นให้เสร็จมากกว่าปล่อยให้นักพัฒนาใช้คำแนะนำบางอย่าง”

แต่แม้ว่า PostgreSQL จะไม่อนุญาตให้ "ภายนอก" ควบคุมตัวเอง แต่ก็ทำได้อย่างสมบูรณ์แบบ ดูสิ่งที่เกิดขึ้นในตัวเขาเมื่อคุณเรียกใช้แบบสอบถาม และจุดที่มีปัญหา

การเพิ่มประสิทธิภาพการสืบค้น PostgreSQL เป็นกลุ่ม คิริลล์ โบโรวิคอฟ (เทนเซอร์)

โดยทั่วไปแล้ว นักพัฒนา [สำหรับ DBA] มักมีปัญหาแบบคลาสสิกอะไรบ้าง? “ที่นี่เราปฏิบัติตามคำขอและ ทุกอย่างช้าไปกับเราทุกอย่างค้าง มีบางอย่างเกิดขึ้น... ปัญหาบางอย่าง!”

เหตุผลเกือบจะเหมือนกันทุกครั้ง:

  • อัลกอริธึมการสืบค้นที่ไม่มีประสิทธิภาพ
    นักพัฒนา: "ตอนนี้ฉันกำลังให้ตาราง SQL แก่เขา 10 ตารางผ่านทาง JOIN..." - และคาดหวังว่าเงื่อนไขของเขาจะ "แก้" อย่างมีประสิทธิภาพอย่างน่าอัศจรรย์ และเขาจะได้ทุกอย่างอย่างรวดเร็ว แต่ปาฏิหาริย์จะไม่เกิดขึ้นและระบบใด ๆ ที่มีความแปรปรวนดังกล่าว (10 ตารางในหนึ่ง FROM) มักจะให้ข้อผิดพลาดบางอย่างเสมอ [บทความ]
  • สถิติที่ไม่เกี่ยวข้อง
    ประเด็นนี้มีความเกี่ยวข้องอย่างมากกับ PostgreSQL โดยเฉพาะ เมื่อคุณ “เท” ชุดข้อมูลขนาดใหญ่ลงบนเซิร์ฟเวอร์ ร้องขอ และมันจะ “แปลงเพศ” แท็บเล็ตของคุณ เพราะเมื่อวานมี 10 บันทึกอยู่ในนั้น และวันนี้มี 10 ล้าน แต่ PostgreSQL ยังไม่ทราบเรื่องนี้ และเราจำเป็นต้องบอกเรื่องนี้ [บทความ]
  • "ปลั๊ก" กับทรัพยากร
    คุณได้ติดตั้งฐานข้อมูลขนาดใหญ่และโหลดจำนวนมากบนเซิร์ฟเวอร์ที่อ่อนแอซึ่งมีดิสก์ หน่วยความจำ หรือประสิทธิภาพของตัวประมวลผลไม่เพียงพอ นั่นคือทั้งหมด... ที่ไหนสักแห่งที่มีเพดานการแสดงซึ่งคุณไม่สามารถกระโดดได้อีกต่อไป
  • การปิดกั้น
    นี่เป็นจุดที่ยาก แต่มีความเกี่ยวข้องมากที่สุดสำหรับการแก้ไขแบบสอบถามต่างๆ (INSERT, UPDATE, DELETE) - นี่เป็นหัวข้อใหญ่แยกต่างหาก

กำลังได้รับแผน

...และสำหรับทุกสิ่งทุกอย่างของเรา ต้องการแผน! เราจำเป็นต้องดูว่าเกิดอะไรขึ้นภายในเซิร์ฟเวอร์

การเพิ่มประสิทธิภาพการสืบค้น PostgreSQL เป็นกลุ่ม คิริลล์ โบโรวิคอฟ (เทนเซอร์)

แผนการดำเนินการสืบค้นสำหรับ PostgreSQL เป็นแผนผังของอัลกอริธึมการดำเนินการสืบค้นในการแสดงข้อความ เป็นอัลกอริทึมที่แน่นอนซึ่งพบว่ามีประสิทธิภาพมากที่สุดจากการวิเคราะห์โดยผู้วางแผน

แต่ละโหนดต้นไม้เป็นการดำเนินการ: การดึงข้อมูลจากตารางหรือดัชนี การสร้างบิตแมป การเข้าร่วมสองตาราง การเข้าร่วม การตัดกัน หรือการยกเว้นส่วนที่เลือก การดำเนินการค้นหาเกี่ยวข้องกับการเดินผ่านโหนดของแผนผังนี้

หากต้องการรับแผนแบบสอบถาม วิธีที่ง่ายที่สุดคือดำเนินการคำสั่ง EXPLAIN. เพื่อให้ได้คุณลักษณะจริงทั้งหมด นั่นคือ ดำเนินการสืบค้นบนฐานจริง ๆ - EXPLAIN (ANALYZE, BUFFERS) SELECT ....

ส่วนที่แย่: เมื่อคุณรันมัน มันจะเกิดขึ้น "ที่นี่และเดี๋ยวนี้" ดังนั้นจึงเหมาะสำหรับการดีบักในเครื่องเท่านั้น หากคุณใช้เซิร์ฟเวอร์ที่มีการโหลดสูงซึ่งอยู่ภายใต้การเปลี่ยนแปลงข้อมูลจำนวนมาก และคุณเห็น: “โอ้! ที่นี่เรามีการดำเนินการที่ช้าเซี่ย ขอ." ครึ่งชั่วโมง หนึ่งชั่วโมงที่แล้ว - ขณะที่คุณกำลังเรียกใช้และรับคำขอนี้จากบันทึก และนำคำขอกลับมาที่เซิร์ฟเวอร์ ชุดข้อมูลและสถิติทั้งหมดของคุณเปลี่ยนไป คุณรันมันเพื่อแก้ไขข้อบกพร่อง - และมันจะรันอย่างรวดเร็ว! และคุณไม่สามารถเข้าใจว่าทำไมทำไม มันเป็น ช้า.

การเพิ่มประสิทธิภาพการสืบค้น PostgreSQL เป็นกลุ่ม คิริลล์ โบโรวิคอฟ (เทนเซอร์)

เพื่อให้เข้าใจถึงสิ่งที่เกิดขึ้นในขณะที่คำขอถูกดำเนินการบนเซิร์ฟเวอร์ คนฉลาดเขียนไว้ โมดูลอธิบายอัตโนมัติ. มีอยู่ในการกระจาย PostgreSQL ทั่วไปเกือบทั้งหมด และสามารถเปิดใช้งานได้ในไฟล์กำหนดค่า

หากพบว่าคำขอบางรายการทำงานนานกว่าขีดจำกัดที่คุณแจ้ง คำขอนั้นก็จะทำงานนานกว่านั้น “ภาพรวม” ของแผนคำขอนี้และเขียนไว้ด้วยกันในบันทึก.

การเพิ่มประสิทธิภาพการสืบค้น PostgreSQL เป็นกลุ่ม คิริลล์ โบโรวิคอฟ (เทนเซอร์)

ตอนนี้ทุกอย่างดูดีขึ้นแล้ว เราไปที่ท่อนไม้แล้วดูที่นั่น... [ข้อความ ผ้าเช็ดเท้า] แต่เราไม่สามารถพูดอะไรเกี่ยวกับมันได้ นอกเหนือจากข้อเท็จจริงที่ว่ามันเป็นแผนที่ยอดเยี่ยมเพราะใช้เวลาดำเนินการ 11 มิลลิวินาที

ดูเหมือนทุกอย่างจะเรียบร้อยดี แต่ไม่มีอะไรชัดเจนว่าเกิดอะไรขึ้นจริงๆ นอกจากเวลาทั่วไปแล้วเรายังไม่เห็นอะไรเลยจริงๆ เนื่องจากการดูข้อความธรรมดาแบบ "ลูกแกะ" เช่นนี้มักไม่สามารถมองเห็นได้

แต่ถึงแม้จะไม่ชัดเจนถึงแม้จะไม่สะดวก แต่ก็ยังมีปัญหาพื้นฐานอีกมากมาย:

  • โหนดบ่งชี้ ผลรวมของทรัพยากรของทรีย่อยทั้งหมด ใต้เขา นั่นคือ คุณไม่สามารถรู้แค่ว่าใช้เวลาไปเท่าไรในการสแกนดัชนีนี้โดยเฉพาะ หากมีเงื่อนไขซ้อนกันอยู่ข้างใต้ เราต้องพิจารณาแบบไดนามิกเพื่อดูว่ามี "ลูก" และตัวแปรตามเงื่อนไข CTE อยู่ภายในหรือไม่ และลบทั้งหมดนี้ "ในจิตใจของเรา"
  • จุดที่สอง: เวลาที่ระบุบนโหนดคือ เวลาดำเนินการของโหนดเดียว. หากโหนดนี้ถูกดำเนินการเป็นผลจากการบันทึกตารางแบบวนซ้ำหลายครั้ง จำนวนการวนซ้ำ—รอบของโหนดนี้—จะเพิ่มขึ้นในแผน แต่เวลาดำเนินการของอะตอมมิกนั้นยังคงเหมือนเดิมในแง่ของแผน นั่นคือเพื่อที่จะเข้าใจว่าโหนดนี้ใช้งานได้นานแค่ไหนคุณต้องคูณสิ่งหนึ่งด้วยสิ่งอื่น - อีกครั้ง "ในหัวของคุณ"

ในสถานการณ์เช่นนี้ ให้ทำความเข้าใจว่า “ใครคือจุดอ่อนที่สุด” แทบจะเป็นไปไม่ได้เลย ดังนั้นแม้แต่นักพัฒนาเองก็เขียนไว้ใน “คู่มือ” ว่า “การทำความเข้าใจแผนงานเป็นศิลปะที่ต้องเรียนรู้ ประสบการณ์...”.

แต่เรามีนักพัฒนา 1000 คน และคุณไม่สามารถถ่ายทอดประสบการณ์นี้ให้กับพวกเขาแต่ละคนได้ ฉัน คุณ เขารู้ แต่คนที่อยู่ที่นั่นไม่รู้อีกต่อไป บางทีเขาอาจจะได้เรียนรู้หรืออาจจะไม่ได้ แต่เขาต้องทำงานตอนนี้ - และเขาจะได้รับประสบการณ์นี้จากที่ไหน?

การแสดงภาพแผน

ดังนั้นเราจึงตระหนักว่าเพื่อที่จะจัดการกับปัญหาเหล่านี้เราจำเป็นต้องมี การแสดงภาพแผนที่ดี. [บทความ]

การเพิ่มประสิทธิภาพการสืบค้น PostgreSQL เป็นกลุ่ม คิริลล์ โบโรวิคอฟ (เทนเซอร์)

ก่อนอื่นเราไป "ผ่านตลาด" - มาดูบนอินเทอร์เน็ตเพื่อดูว่ามีอะไรอยู่บ้าง

แต่ปรากฎว่ามีโซลูชัน "สด" ค่อนข้างน้อยมากที่มีการพัฒนาไม่มากก็น้อย - แท้จริงแล้วมีเพียงโซลูชันเดียวเท่านั้น: exp.depesz.com โดย ฮูเบิร์ต ลูบัคซิวสกี้ เมื่อคุณป้อนข้อความแทนแผนลงในช่อง "ฟีด" มันจะแสดงตารางพร้อมข้อมูลที่แยกวิเคราะห์:

  • เวลาประมวลผลของโหนดเอง
  • เวลาทั้งหมดสำหรับทรีย่อยทั้งหมด
  • จำนวนบันทึกที่ถูกดึงมาซึ่งเป็นไปตามที่คาดไว้ทางสถิติ
  • ตัวโหนดเอง

บริการนี้ยังมีความสามารถในการแชร์ลิงก์ที่เก็บถาวร คุณโยนแผนของคุณลงไปแล้วพูดว่า: "เฮ้ วาสยา นี่คือลิงค์ มีบางอย่างผิดปกติ"

การเพิ่มประสิทธิภาพการสืบค้น PostgreSQL เป็นกลุ่ม คิริลล์ โบโรวิคอฟ (เทนเซอร์)

แต่ก็มีปัญหาเล็กน้อยเช่นกัน

ประการแรก "คัดลอก-วาง" จำนวนมาก คุณหยิบท่อนไม้มาติดไว้ตรงนั้น ซ้ำ และอีกครั้ง

ประการที่สอง ไม่มีการวิเคราะห์ปริมาณข้อมูลที่อ่าน — บัฟเฟอร์เดียวกับที่เอาต์พุต EXPLAIN (ANALYZE, BUFFERS)เราไม่เห็นมันที่นี่ เขาไม่รู้วิธีแยกชิ้นส่วน ทำความเข้าใจ และทำงานร่วมกับพวกเขา เมื่อคุณอ่านข้อมูลจำนวนมากและพบว่าคุณอาจจัดสรรดิสก์และแคชหน่วยความจำผิด ข้อมูลนี้มีความสำคัญมาก

จุดลบประการที่สามคือการพัฒนาโครงการนี้อ่อนแอมาก คอมมิตมีขนาดเล็กมาก จะดีถ้าทุกๆ หกเดือน และโค้ดอยู่ใน Perl

การเพิ่มประสิทธิภาพการสืบค้น PostgreSQL เป็นกลุ่ม คิริลล์ โบโรวิคอฟ (เทนเซอร์)

แต่นี่คือ "เนื้อเพลง" ทั้งหมดเราสามารถอยู่กับสิ่งนี้ได้ แต่มีสิ่งหนึ่งที่ทำให้เราละทิ้งบริการนี้อย่างมาก นี่เป็นข้อผิดพลาดในการวิเคราะห์ Common Table Expression (CTE) และโหนดไดนามิกต่างๆ เช่น InitPlan/SubPlan

หากคุณเชื่อภาพนี้ เวลาดำเนินการทั้งหมดของแต่ละโหนดจะมากกว่าเวลาดำเนินการทั้งหมดของคำขอทั้งหมด มันง่ายมาก - เวลาการสร้างของ CTE นี้ไม่ได้ถูกลบออกจากโหนดการสแกน CTE. ดังนั้นเราจึงไม่ทราบคำตอบที่ถูกต้องอีกต่อไปว่าการสแกน CTE นั้นใช้เวลานานเท่าใด

การเพิ่มประสิทธิภาพการสืบค้น PostgreSQL เป็นกลุ่ม คิริลล์ โบโรวิคอฟ (เทนเซอร์)

แล้วเราก็รู้ว่าถึงเวลาเขียนของเราเองแล้ว ไชโย! นักพัฒนาทุกคนพูดว่า: “ตอนนี้เราจะเขียนของเราเอง มันจะง่ายมาก!”

เราใช้สแต็กทั่วไปสำหรับบริการเว็บ: แกนหลักที่ใช้ Node.js + Express ใช้ Bootstrap และ D3.js สำหรับไดอะแกรมที่สวยงาม และความคาดหวังของเราก็สมเหตุสมผล - เราได้รับต้นแบบแรกใน 2 สัปดาห์:

  • ตัวแยกวิเคราะห์แผนแบบกำหนดเอง
    นั่นคือตอนนี้เราสามารถแยกวิเคราะห์แผนใดๆ จากแผนที่สร้างโดย PostgreSQL ได้
  • การวิเคราะห์โหนดไดนามิกที่ถูกต้อง - การสแกน CTE, InitPlan, แผนย่อย
  • การวิเคราะห์การกระจายตัวของบัฟเฟอร์ - โดยที่หน้าข้อมูลถูกอ่านจากหน่วยความจำ โดยที่จากแคชในเครื่อง และจากดิสก์
  • ได้รับความชัดเจน
    เพื่อไม่ให้ "ขุด" ทั้งหมดนี้ในบันทึก แต่จะเห็น "ลิงก์ที่อ่อนแอที่สุด" ทันทีในภาพ

การเพิ่มประสิทธิภาพการสืบค้น PostgreSQL เป็นกลุ่ม คิริลล์ โบโรวิคอฟ (เทนเซอร์)

เรามีอะไรแบบนี้ โดยมีการเน้นไวยากรณ์รวมอยู่ด้วย แต่โดยปกติแล้วนักพัฒนาของเราจะไม่ทำงานกับการนำเสนอแผนอย่างสมบูรณ์อีกต่อไป แต่จะใช้แผนที่สั้นกว่า ท้ายที่สุดเราได้แยกวิเคราะห์ตัวเลขทั้งหมดแล้วโยนไปทางซ้ายและขวาและตรงกลางเราเหลือเพียงบรรทัดแรกว่าเป็นโหนดประเภทใด: CTE Scan, การสร้าง CTE หรือ Seq Scan ตามสัญญาณบางอย่าง

นี่คือการแสดงแบบย่อที่เราเรียกว่า แม่แบบแผน.

การเพิ่มประสิทธิภาพการสืบค้น PostgreSQL เป็นกลุ่ม คิริลล์ โบโรวิคอฟ (เทนเซอร์)

อะไรจะสะดวกอีกล่ะ? มันจะสะดวกกว่าที่จะดูว่าส่วนแบ่งเวลาทั้งหมดของเราถูกจัดสรรให้กับโหนดใด - และเพียงแค่ "ติดไว้" ที่ด้านข้าง แผนภูมิวงกลม.

เราชี้ไปที่โหนดแล้วดูว่า ปรากฎว่า Seq Scan ใช้เวลาน้อยกว่าหนึ่งในสี่ของเวลาทั้งหมด และ 3/4 ที่เหลือถูกใช้โดย CTE Scan สยองขวัญ! นี่เป็นหมายเหตุเล็กๆ น้อยๆ เกี่ยวกับ "อัตราการยิง" ของ CTE Scan หากคุณใช้สิ่งเหล่านี้ในการสืบค้น มันไม่เร็วมาก - ด้อยกว่าการสแกนตารางทั่วไปด้วยซ้ำ [บทความ] [บทความ]

แต่โดยปกติแล้วไดอะแกรมดังกล่าวจะน่าสนใจกว่าและซับซ้อนกว่า เมื่อเราชี้ไปที่เซ็กเมนต์ทันทีและดูว่ามากกว่าครึ่งหนึ่งของเวลาที่ Seq Scan "กิน" นอกจากนี้ยังมีตัวกรองบางชนิดอยู่ข้างใน บันทึกจำนวนมากถูกทิ้งตามนั้น... คุณสามารถส่งรูปภาพนี้ไปยังนักพัฒนาโดยตรงแล้วพูดว่า: "Vasya ทุกอย่างแย่สำหรับคุณที่นี่! คิดดูสิ - มีบางอย่างผิดปกติ!”

การเพิ่มประสิทธิภาพการสืบค้น PostgreSQL เป็นกลุ่ม คิริลล์ โบโรวิคอฟ (เทนเซอร์)

แน่นอนว่ามี "คราด" อยู่บ้าง

สิ่งแรกที่เราเจอคือปัญหาการปัดเศษ เวลาของแต่ละโหนดในแผนจะแสดงด้วยความแม่นยำ 1 μs และเมื่อจำนวนรอบของโหนดเกิน เช่น 1000 - หลังจากดำเนินการ PostgreSQL หาร "ภายในความแม่นยำ" จากนั้นเมื่อคำนวณย้อนกลับ เราจะได้เวลารวม "ที่ใดที่หนึ่งระหว่าง 0.95ms ถึง 1.05ms" เมื่อนับไปเป็นไมโครวินาที ก็ไม่เป็นไร แต่เมื่อถึง [มิลลิ] วินาทีแล้ว คุณจะต้องคำนึงถึงข้อมูลนี้เมื่อทำการ "ผูก" ทรัพยากรเข้ากับโหนดของแผน "ใครใช้ไปมากน้อยเพียงใด"

การเพิ่มประสิทธิภาพการสืบค้น PostgreSQL เป็นกลุ่ม คิริลล์ โบโรวิคอฟ (เทนเซอร์)

จุดที่สองที่ซับซ้อนกว่าคือการกระจายทรัพยากร (บัฟเฟอร์เหล่านั้น) ระหว่างโหนดไดนามิก ซึ่งทำให้เราต้องเสียค่าใช้จ่ายใน 2 สัปดาห์แรกของต้นแบบบวกอีก 4 สัปดาห์

ปัญหาประเภทนี้ค่อนข้างง่าย - เราทำ CTE และน่าจะอ่านอะไรบางอย่างในนั้น อันที่จริง PostgreSQL นั้น "ฉลาด" และจะไม่อ่านอะไรโดยตรงที่นั่น จากนั้นเราก็นำบันทึกแรกจากนั้น และบันทึกหนึ่งร้อยคนแรกจาก CTE เดียวกัน

การเพิ่มประสิทธิภาพการสืบค้น PostgreSQL เป็นกลุ่ม คิริลล์ โบโรวิคอฟ (เทนเซอร์)

เราดูแผนและเข้าใจ เป็นเรื่องแปลกที่เรามีบัฟเฟอร์ 3 ตัว (หน้าข้อมูล) “ใช้ไป” ใน Seq Scan, อีก 1 ตัวใน CTE Scan และอีก 2 ตัวใน CTE Scan ครั้งที่สอง นั่นคือถ้าเราสรุปทุกอย่างเราจะได้ 6 แต่จากแท็บเล็ตเราอ่านได้เพียง 3 เท่านั้น! CTE Scan ไม่ได้อ่านข้อมูลจากทุกที่ แต่ทำงานโดยตรงกับหน่วยความจำกระบวนการ นั่นคือมีบางอย่างผิดปกติที่นี่!

ในความเป็นจริงปรากฎว่านี่คือข้อมูลทั้งหมด 3 หน้าที่ถูกร้องขอจาก Seq Scan ครั้งแรก 1 ขอให้สแกน CTE ครั้งที่ 1 จากนั้นหน้าที่ 2 และอีก 2 หน้าถูกอ่านให้เขาฟัง นั่นคือทั้งหมด ข้อมูลการอ่าน 3 หน้า ไม่ใช่ 6 หน้า

การเพิ่มประสิทธิภาพการสืบค้น PostgreSQL เป็นกลุ่ม คิริลล์ โบโรวิคอฟ (เทนเซอร์)

และภาพนี้ทำให้เราเข้าใจว่าการดำเนินการตามแผนนั้นไม่ใช่ต้นไม้อีกต่อไป แต่เป็นเพียงกราฟแบบอะไซเคิลบางประเภท และเราได้แผนภาพแบบนี้ เพื่อที่เราจะได้เข้าใจว่า "อะไรมาจากไหนตั้งแต่แรก" นั่นคือที่นี่เราสร้าง CTE จาก pg_class และขอมันสองครั้ง และเวลาเกือบทั้งหมดของเราถูกใช้ไปที่สาขาเมื่อเราขอมันเป็นครั้งที่ 2 เห็นได้ชัดว่าการอ่านรายการที่ 101 มีราคาแพงกว่าการอ่านรายการที่ 1 จากแท็บเล็ตมาก

การเพิ่มประสิทธิภาพการสืบค้น PostgreSQL เป็นกลุ่ม คิริลล์ โบโรวิคอฟ (เทนเซอร์)

เราหายใจออกสักพัก พวกเขาพูดว่า: "เอาล่ะ นีโอ คุณรู้จักกังฟูแล้ว! ตอนนี้ประสบการณ์ของเราอยู่บนหน้าจอของคุณแล้ว ตอนนี้คุณสามารถใช้มันได้แล้ว" [บทความ]

การรวมบันทึก

นักพัฒนา 1000 คนของเราถอนหายใจด้วยความโล่งอก แต่เราเข้าใจว่าเรามีเซิร์ฟเวอร์ "ต่อสู้" หลายร้อยเครื่องเท่านั้น และการ "คัดลอกวาง" ทั้งหมดนี้โดยนักพัฒนาไม่สะดวกเลย เราตระหนักว่าเราต้องรวบรวมมันเอง

การเพิ่มประสิทธิภาพการสืบค้น PostgreSQL เป็นกลุ่ม คิริลล์ โบโรวิคอฟ (เทนเซอร์)

โดยทั่วไปมีโมดูลมาตรฐานที่สามารถรวบรวมสถิติได้ แต่จำเป็นต้องเปิดใช้งานในการกำหนดค่าด้วย - นี่คือ โมดูล pg_stat_statements. แต่เขาไม่เหมาะกับเรา

ประการแรก จะกำหนดให้กับแบบสอบถามเดียวกันโดยใช้รูปแบบที่แตกต่างกันภายในฐานข้อมูลเดียวกัน QueryId ที่แตกต่างกัน. นั่นคือถ้าคุณทำครั้งแรก SET search_path = '01'; SELECT * FROM user LIMIT 1;แล้ว SET search_path = '02'; และคำขอเดียวกัน สถิติของโมดูลนี้จะมีบันทึกที่แตกต่างกัน และฉันจะไม่สามารถรวบรวมสถิติทั่วไปโดยเฉพาะในบริบทของโปรไฟล์คำขอนี้ โดยไม่คำนึงถึงรูปแบบ

จุดที่สองที่ทำให้เราใช้ไม่ได้คือ ขาดแผน. นั่นคือไม่มีแผนมีแต่คำขอเท่านั้นเอง เราเห็นสิ่งที่ช้าลง แต่เราไม่เข้าใจว่าทำไม และที่นี่เรากลับมาที่ปัญหาของชุดข้อมูลที่เปลี่ยนแปลงอย่างรวดเร็ว

และช่วงเวลาสุดท้าย- ขาด "ข้อเท็จจริง". นั่นคือ คุณไม่สามารถระบุอินสแตนซ์เฉพาะของการดำเนินการค้นหาได้ ไม่มีเลย มีเพียงสถิติแบบรวมเท่านั้น แม้ว่าจะสามารถทำงานร่วมกับสิ่งนี้ได้ แต่ก็เป็นเรื่องยากมาก

การเพิ่มประสิทธิภาพการสืบค้น PostgreSQL เป็นกลุ่ม คิริลล์ โบโรวิคอฟ (เทนเซอร์)

ดังนั้นเราจึงตัดสินใจที่จะต่อสู้กับการคัดลอกและวางและเริ่มเขียน สะสม.

ตัวรวบรวมเชื่อมต่อผ่าน SSH สร้างการเชื่อมต่อที่ปลอดภัยไปยังเซิร์ฟเวอร์ด้วยฐานข้อมูลโดยใช้ใบรับรอง และ tail -F “เกาะติด” กับมันในไฟล์บันทึก ดังนั้นในเซสชั่นนี้ เราได้รับ "มิเรอร์" ที่สมบูรณ์ของไฟล์บันทึกทั้งหมดซึ่งเซิร์ฟเวอร์สร้างขึ้น โหลดบนเซิร์ฟเวอร์นั้นมีน้อยมาก เนื่องจากเราไม่ได้แยกวิเคราะห์อะไรเลย เราแค่จำลองการรับส่งข้อมูลเท่านั้น

เนื่องจากเราได้เริ่มเขียนอินเทอร์เฟซใน Node.js แล้ว เราจึงเขียน Collector ต่อไป และเทคโนโลยีนี้ได้พิสูจน์ตัวเองแล้วเนื่องจากสะดวกมากที่จะใช้ JavaScript ในการทำงานกับข้อมูลข้อความที่มีรูปแบบอ่อนแอซึ่งก็คือบันทึก และโครงสร้างพื้นฐาน Node.js เองก็เป็นแพลตฟอร์มแบ็กเอนด์ช่วยให้คุณทำงานกับการเชื่อมต่อเครือข่ายได้อย่างง่ายดายและสะดวก และกับสตรีมข้อมูลใดๆ ก็ได้

ดังนั้นเราจึง "ขยาย" การเชื่อมต่อสองประการ: ครั้งแรกที่ "ฟัง" บันทึกและนำไปเองและครั้งที่สองเพื่อถามฐานเป็นระยะ “แต่บันทึกแสดงว่าสัญญาณที่มี oid 123 ถูกบล็อก” แต่สิ่งนี้ไม่ได้มีความหมายอะไรสำหรับนักพัฒนา และเป็นการดีที่จะถามฐานข้อมูลว่า “OID = 123 คืออะไร” ดังนั้นเราจึงถามฐานเป็นระยะถึงสิ่งที่เรายังไม่ทราบเกี่ยวกับตัวเรา

การเพิ่มประสิทธิภาพการสืบค้น PostgreSQL เป็นกลุ่ม คิริลล์ โบโรวิคอฟ (เทนเซอร์)

“มีสิ่งเดียวที่คุณไม่ได้คำนึงถึง นั่นคือผึ้งที่มีลักษณะคล้ายช้างสายพันธุ์หนึ่ง!” เราเริ่มพัฒนาระบบนี้เมื่อเราต้องการตรวจสอบเซิร์ฟเวอร์ 10 เครื่อง สิ่งที่สำคัญที่สุดในความเข้าใจของเราคือปัญหาบางอย่างเกิดขึ้นซึ่งยากต่อการจัดการ แต่ในช่วงไตรมาสแรก เราได้รับเงินหนึ่งร้อยสำหรับการตรวจสอบ - เนื่องจากระบบใช้งานได้ ทุกคนต้องการมัน ทุกคนสบายใจ

ทั้งหมดนี้จำเป็นต้องเพิ่ม กระแสข้อมูลมีขนาดใหญ่และแอคทีฟ ในความเป็นจริงแล้ว สิ่งที่เราตรวจสอบ สิ่งที่เราจัดการได้ ก็คือสิ่งที่เราใช้ เรายังใช้ PostgreSQL เป็นที่จัดเก็บข้อมูลอีกด้วย และไม่มีอะไรจะ "เท" ข้อมูลลงไปได้เร็วไปกว่าผู้ปฏิบัติงาน COPY ยัง.

แต่การ "เท" ข้อมูลเพียงอย่างเดียวไม่ใช่เทคโนโลยีของเราจริงๆ เพราะหากคุณมีคำขอประมาณ 50 ต่อวินาทีบนเซิร์ฟเวอร์นับร้อยเซิร์ฟเวอร์ สิ่งนี้จะสร้างบันทึกได้ 100-150GB ต่อวัน ดังนั้นเราจึงต้อง "ตัด" ฐานอย่างระมัดระวัง

ประการแรกเราทำ แบ่งตามวันเพราะโดยส่วนใหญ่แล้ว ไม่มีใครสนใจความสัมพันธ์ระหว่างวัน สิ่งที่สร้างความแตกต่างให้กับสิ่งที่คุณมีเมื่อวานนี้ ถ้าคืนนี้คุณเปิดตัวแอปพลิเคชันเวอร์ชันใหม่ - และมีสถิติใหม่อยู่แล้ว

ประการที่สอง เราได้เรียนรู้ (ถูกบังคับ) รวดเร็วมากในการเขียนโดยใช้ COPY. นั่นก็คือ ไม่ใช่แค่เท่านั้น COPYเพราะเขาเร็วกว่า INSERTและเร็วขึ้นอีกด้วย

การเพิ่มประสิทธิภาพการสืบค้น PostgreSQL เป็นกลุ่ม คิริลล์ โบโรวิคอฟ (เทนเซอร์)

จุดที่สาม - ฉันต้องทำ ละทิ้งทริกเกอร์ตามลำดับและคีย์ต่างประเทศ. นั่นคือเราไม่มีความสมบูรณ์ในการอ้างอิงเลย เพราะถ้าคุณมีตารางที่มี FK คู่หนึ่ง และคุณพูดในโครงสร้างฐานข้อมูลว่า “นี่คือบันทึกบันทึกที่ FK อ้างอิงถึงกลุ่มของบันทึก เป็นต้น” จากนั้นเมื่อคุณแทรกมัน PostgreSQL ไม่เหลืออะไรนอกจากจะรับและทำอย่างตรงไปตรงมา SELECT 1 FROM master_fk1_table WHERE ... ด้วยตัวระบุที่คุณพยายามแทรก - เพียงเพื่อตรวจสอบว่ามีบันทึกนี้อยู่ที่นั่น และคุณไม่ "แยก" Foreign Key นี้ด้วยการแทรกของคุณ

แทนที่จะบันทึกเพียงระเบียนเดียวในตารางเป้าหมายและดัชนี เราได้รับประโยชน์เพิ่มเติมจากการอ่านจากตารางทั้งหมดที่ตารางอ้างอิงถึง แต่เราไม่ต้องการสิ่งนี้เลย - งานของเราคือบันทึกให้มากที่สุดเท่าที่จะเป็นไปได้และรวดเร็วที่สุดโดยให้โหลดน้อยที่สุด ดังนั้น FK - ลง!

จุดต่อไปคือการรวมและการแฮช เริ่มแรกเรานำไปใช้ในฐานข้อมูล - ท้ายที่สุดจะสะดวกที่จะทำในแท็บเล็ตบางประเภททันทีเมื่อมีบันทึกมาถึง "บวกหนึ่ง" ตรงไกปืน. สะดวก แต่ก็แย่เหมือนกัน - คุณใส่บันทึกหนึ่งรายการ แต่ถูกบังคับให้อ่านและเขียนอย่างอื่นจากตารางอื่น ยิ่งกว่านั้นคุณไม่เพียงแต่อ่านและเขียนเท่านั้น แต่ยังทำทุกครั้งอีกด้วย

ทีนี้ลองจินตนาการว่าคุณมีตารางที่คุณเพียงแค่นับจำนวนคำขอที่ส่งผ่านโฮสต์เฉพาะ: +1, +1, +1, ..., +1. โดยหลักการแล้วคุณไม่ต้องการสิ่งนี้ - เป็นไปได้ทั้งหมด ผลรวมในหน่วยความจำบนตัวสะสม และส่งเข้าฐานข้อมูลได้ในคราวเดียว +10.

ใช่ ในกรณีที่เกิดปัญหาบางอย่าง ความสมบูรณ์ทางตรรกะของคุณอาจ "พังทลาย" แต่นี่เป็นกรณีที่แทบจะเป็นไปไม่ได้เลย เนื่องจากคุณมีเซิร์ฟเวอร์ปกติ มีแบตเตอรี่อยู่ในตัวควบคุม คุณมีบันทึกธุรกรรม บันทึกบน ระบบไฟล์... โดยทั่วไปแล้วไม่คุ้มเลย การสูญเสียประสิทธิภาพการทำงานที่คุณได้รับจากการเรียกใช้ทริกเกอร์/FK นั้นไม่คุ้มกับค่าใช้จ่ายที่คุณได้รับ

มันเหมือนกันกับการแฮช คำขอบางอย่างส่งถึงคุณ คุณคำนวณตัวระบุบางอย่างจากคำขอนั้นในฐานข้อมูล เขียนลงในฐานข้อมูล แล้วแจ้งให้ทุกคนทราบ ทุกอย่างเรียบร้อยดีจนกระทั่งมีคนที่สองเข้ามาหาคุณและต้องการจะบันทึกสิ่งเดียวกัน และคุณถูกบล็อก ซึ่งนี่ถือว่าแย่แล้ว ดังนั้นหากคุณสามารถถ่ายโอนการสร้าง ID บางส่วนไปยังไคลเอนต์ได้ (สัมพันธ์กับฐานข้อมูล) จะเป็นการดีกว่าถ้าทำเช่นนี้

เหมาะอย่างยิ่งสำหรับเราที่จะใช้ MD5 จากข้อความ - คำขอ แผน เทมเพลต... เราคำนวณจากฝั่งตัวรวบรวม และ "เท" ID สำเร็จรูปลงในฐานข้อมูล ความยาวของ MD5 และการแบ่งพาร์ติชั่นรายวันทำให้เราไม่ต้องกังวลกับการชนกันที่อาจเกิดขึ้น

การเพิ่มประสิทธิภาพการสืบค้น PostgreSQL เป็นกลุ่ม คิริลล์ โบโรวิคอฟ (เทนเซอร์)

แต่เพื่อที่จะบันทึกทั้งหมดนี้ได้อย่างรวดเร็ว เราจำเป็นต้องแก้ไขขั้นตอนการบันทึกด้วยตัวเอง

ปกติคุณเขียนข้อมูลอย่างไร? เรามีชุดข้อมูลบางประเภท เราแยกมันออกเป็นหลายตาราง แล้วคัดลอกมัน - อันดับแรกเป็นชุดแรก จากนั้นเป็นชุดที่สอง เป็นชุดที่สาม... มันไม่สะดวกเพราะดูเหมือนว่าเราจะเขียนสตรีมข้อมูลเดียวในสามขั้นตอน ตามลำดับ ไม่น่าพึงพอใจ. สามารถทำได้เร็วขึ้นหรือไม่? สามารถ!

ในการทำเช่นนี้ก็เพียงพอแล้วที่จะสลายกระแสเหล่านี้ไปพร้อม ๆ กัน ปรากฎว่าเรามีข้อผิดพลาด คำขอ เทมเพลต การบล็อก ... การบินแยกเธรด - และเราเขียนทั้งหมดพร้อมกัน เพียงพอสำหรับสิ่งนี้ เปิดช่อง COPY ไว้อย่างต่อเนื่องสำหรับตารางเป้าหมายแต่ละตาราง.

การเพิ่มประสิทธิภาพการสืบค้น PostgreSQL เป็นกลุ่ม คิริลล์ โบโรวิคอฟ (เทนเซอร์)

นั่นคือที่นักสะสม มีกระแสน้ำอยู่เสมอซึ่งฉันสามารถเขียนข้อมูลที่ฉันต้องการได้ แต่เพื่อให้ฐานข้อมูลเห็นข้อมูลนี้ และมีคนไม่ติดขัดในการรอข้อมูลนี้ที่จะเขียน COPY จะต้องถูกขัดจังหวะในช่วงเวลาหนึ่ง. สำหรับเรา ระยะเวลาที่มีประสิทธิภาพสูงสุดคือประมาณ 100 มิลลิวินาที - เราปิดและเปิดอีกครั้งในตารางเดิมทันที และหากเรามีโฟลว์ไม่เพียงพอในช่วงพีคบางจุด เราก็จะรวมกันได้ถึงขีดจำกัดที่แน่นอน

นอกจากนี้ เราพบว่าสำหรับโปรไฟล์โหลดดังกล่าว การรวมตัวใดๆ เมื่อมีการรวบรวมบันทึกเป็นชุดถือเป็นสิ่งเลวร้าย ความชั่วร้ายแบบคลาสสิกคือ INSERT ... VALUES และอีก 1000 บันทึก เพราะ ณ จุดนั้น คุณมีจำนวนการเขียนสูงสุดบนสื่อ และทุกคนที่พยายามจะเขียนบางสิ่งลงดิสก์จะต้องรออยู่

เพื่อกำจัดความผิดปกติดังกล่าว อย่าเพิ่งรวมอะไรเข้าด้วยกัน อย่าบัฟเฟอร์เลย. และหากการบัฟเฟอร์ลงดิสก์เกิดขึ้น (โชคดีที่ Stream API ใน Node.js ช่วยให้คุณค้นหาได้) ให้เลื่อนการเชื่อมต่อนี้ออกไป เมื่อคุณได้รับกิจกรรมที่ฟรีอีกครั้ง ให้เขียนถึงกิจกรรมจากคิวสะสม และในขณะที่งานยุ่ง ให้หยิบอันถัดไปฟรีจากสระแล้วเขียนถึงมัน

ก่อนที่จะแนะนำแนวทางนี้ในการบันทึกข้อมูล เรามีการดำเนินการเขียนประมาณ 4K และด้วยวิธีนี้ เราจึงลดภาระลงได้ 4 เท่า ตอนนี้พวกเขาเติบโตขึ้นอีก 6 เท่าเนื่องจากฐานข้อมูลที่ได้รับการตรวจสอบใหม่ - สูงถึง 100MB/s และตอนนี้เราจัดเก็บบันทึกในช่วง 3 เดือนที่ผ่านมาในปริมาณประมาณ 10-15TB โดยหวังว่าภายในเวลาเพียงสามเดือน นักพัฒนาซอฟต์แวร์จะสามารถแก้ไขปัญหาใดๆ ได้

เราเข้าใจปัญหา

แต่การรวบรวมข้อมูลทั้งหมดนี้เป็นสิ่งที่ดี มีประโยชน์ มีความเกี่ยวข้อง แต่ยังไม่เพียงพอ - จำเป็นต้องทำความเข้าใจ เพราะนี่คือแผนที่แตกต่างกันนับล้านแผนต่อวัน

การเพิ่มประสิทธิภาพการสืบค้น PostgreSQL เป็นกลุ่ม คิริลล์ โบโรวิคอฟ (เทนเซอร์)

แต่คนเป็นล้านไม่สามารถจัดการได้ เราต้อง "เล็กลง" ก่อน และก่อนอื่น คุณต้องตัดสินใจว่าจะจัดระเบียบสิ่งที่ "เล็กกว่า" นี้อย่างไร

เราได้ระบุประเด็นสำคัญสามประการ:

  • ใคร ส่งคำขอนี้
    นั่นคือ "มาถึง" จากแอปพลิเคชันใด: เว็บอินเตอร์เฟส แบ็กเอนด์ ระบบการชำระเงิน หรืออย่างอื่น
  • ที่ไหน มันเกิดขึ้น
    บนเซิร์ฟเวอร์ใดโดยเฉพาะ? เพราะหากคุณมีหลายเซิร์ฟเวอร์ภายใต้แอปพลิเคชันเดียว และทันใดนั้นเซิร์ฟเวอร์หนึ่ง "เสีย" (เพราะ "ดิสก์เน่า" "หน่วยความจำรั่ว" และปัญหาอื่น ๆ ) คุณจะต้องระบุที่อยู่เซิร์ฟเวอร์โดยเฉพาะ
  • ในขณะที่ ปัญหาก็แสดงออกมาไม่ทางใดก็ทางหนึ่ง

เพื่อทำความเข้าใจว่า “ใคร” ส่งคำขอถึงเรา เราใช้เครื่องมือมาตรฐาน - การตั้งค่าตัวแปรเซสชัน: SET application_name = '{bl-host}:{bl-method}'; — เราส่งชื่อของโฮสต์ตรรกะทางธุรกิจที่เป็นที่มาของคำขอ และชื่อของวิธีการหรือแอปพลิเคชันที่เริ่มต้นคำขอ

หลังจากที่เราส่ง "เจ้าของ" ของคำขอแล้ว จะต้องส่งออกไปยังบันทึก - สำหรับสิ่งนี้ เรากำหนดค่าตัวแปร log_line_prefix = ' %m [%p:%v] [%d] %r %a'. สำหรับผู้ที่สนใจอาจจะ ดูในคู่มือมันไม่สิ่งที่ทุกคนหมายถึงอะไร. ปรากฎว่าเราเห็นในบันทึก:

  • เวลา
  • ตัวระบุกระบวนการและธุรกรรม
  • ชื่อฐานข้อมูล
  • IP ของบุคคลที่ส่งคำขอนี้
  • และชื่อวิธี

การเพิ่มประสิทธิภาพการสืบค้น PostgreSQL เป็นกลุ่ม คิริลล์ โบโรวิคอฟ (เทนเซอร์)

จากนั้นเราก็ตระหนักว่าการดูความสัมพันธ์ของคำขอเดียวระหว่างเซิร์ฟเวอร์ต่างๆ นั้นไม่น่าสนใจนัก ไม่บ่อยนักที่คุณจะพบสถานการณ์ที่แอปพลิเคชั่นหนึ่งทำงานผิดพลาดเท่ากันที่นี่และที่นั่น แต่ถึงแม้ว่ามันจะเหมือนกัน ลองดูที่เซิร์ฟเวอร์เหล่านี้

นี่คือการตัด "หนึ่งเซิร์ฟเวอร์ - หนึ่งวัน" มันปรากฏว่าเพียงพอสำหรับเราสำหรับการวิเคราะห์ใดๆ

ส่วนการวิเคราะห์แรกจะเหมือนกัน "ตัวอย่าง" - รูปแบบการนำเสนอแผนโดยย่อ ปราศจากตัวบ่งชี้ตัวเลขทั้งหมด การตัดครั้งที่สองคือแอปพลิเคชันหรือวิธีการ และการตัดครั้งที่สามคือโหนดแผนเฉพาะที่ทำให้เราเกิดปัญหา

เมื่อเราย้ายจากอินสแตนซ์เฉพาะไปยังเทมเพลต เรามีข้อดีสองประการพร้อมกัน:

  • การลดจำนวนออบเจ็กต์เพื่อการวิเคราะห์หลายครั้ง
    เราต้องวิเคราะห์ปัญหาไม่ใช่ด้วยแบบสอบถามหรือแผนนับพันอีกต่อไป แต่ด้วยเทมเพลตหลายสิบรายการ
  • เส้นเวลา
    นั่นคือโดยการสรุป “ข้อเท็จจริง” ไว้ในส่วนใดส่วนหนึ่ง คุณจะสามารถแสดงลักษณะที่ปรากฏในระหว่างวันได้ และตรงนี้คุณคงเข้าใจได้ว่าถ้าคุณมีรูปแบบบางอย่างเกิดขึ้น เช่น ชั่วโมงละครั้ง แต่ควรเกิดขึ้นวันละครั้ง คุณควรคิดถึงสิ่งที่ผิดพลาด ใครเป็นคนก่อ และทำไม บางทีมันควรจะอยู่ที่นี่ ไม่ควร นี่เป็นวิธีการวิเคราะห์อีกวิธีหนึ่งที่ไม่ใช่ตัวเลขและเป็นภาพล้วนๆ

การเพิ่มประสิทธิภาพการสืบค้น PostgreSQL เป็นกลุ่ม คิริลล์ โบโรวิคอฟ (เทนเซอร์)

วิธีที่เหลือจะขึ้นอยู่กับตัวบ่งชี้ที่เราแยกออกจากแผน: รูปแบบดังกล่าวเกิดขึ้นกี่ครั้ง เวลาทั้งหมดและเวลาเฉลี่ย จำนวนข้อมูลที่อ่านจากดิสก์ และจำนวนจากหน่วยความจำ...

เพราะตัวอย่างเช่น คุณมาที่หน้าการวิเคราะห์สำหรับโฮสต์ ดูสิ มีบางอย่างเริ่มอ่านมากเกินไปบนดิสก์ ดิสก์บนเซิร์ฟเวอร์ไม่สามารถจัดการได้ - ใครอ่านจากมัน?

และคุณสามารถจัดเรียงตามคอลัมน์ใดก็ได้และตัดสินใจว่าคุณจะจัดการกับอะไรในตอนนี้ - โหลดบนโปรเซสเซอร์หรือดิสก์หรือจำนวนคำขอทั้งหมด... เราจัดเรียงมันดูที่ "ด้านบน" แก้ไขและ เปิดตัวแอปพลิเคชั่นเวอร์ชั่นใหม่
[วิดีโอบรรยาย]

และทันทีที่คุณเห็นแอพพลิเคชั่นต่างๆ ที่มาพร้อมกับเทมเพลตเดียวกันจากคำขอดังกล่าว SELECT * FROM users WHERE login = 'Vasya'. ส่วนหน้า แบ็กเอนด์ การประมวลผล... และคุณสงสัยว่าทำไมการประมวลผลถึงอ่านผู้ใช้ถ้าเขาไม่โต้ตอบกับเขา

วิธีตรงกันข้ามคือการดูทันทีจากแอปพลิเคชันว่ามันทำอะไร ตัวอย่างเช่น ส่วนหน้าคือสิ่งนี้ สิ่งนี้ และสิ่งนี้ ครั้งละครั้ง (ไทม์ไลน์ช่วยได้) และคำถามก็เกิดขึ้นทันที: ดูเหมือนว่าไม่ใช่หน้าที่ของส่วนหน้าที่จะทำอะไรสักอย่างต่อชั่วโมง...

การเพิ่มประสิทธิภาพการสืบค้น PostgreSQL เป็นกลุ่ม คิริลล์ โบโรวิคอฟ (เทนเซอร์)

ผ่านไปสักพักเราก็ตระหนักว่าเราขาดการรวมกลุ่ม สถิติตามโหนดแผน. เราแยกเฉพาะโหนดที่ทำบางอย่างกับข้อมูลของตารางออกจากแผนเท่านั้น (อ่าน/เขียนด้วยดัชนีหรือไม่) ในความเป็นจริง มีการเพิ่มเพียงด้านเดียวเท่านั้นเมื่อเทียบกับภาพก่อนหน้า - โหนดนี้นำบันทึกมาให้เรากี่รายการ?และจำนวนที่ถูกละทิ้ง (แถวถูกลบโดยตัวกรอง)

คุณไม่มีดัชนีที่เหมาะสมบนจาน คุณร้องขอมัน มันบินผ่านดัชนี ตกไปอยู่ใน Seq Scan... คุณได้กรองบันทึกทั้งหมดออกไปแล้ว ยกเว้นบันทึกเดียว เหตุใดคุณจึงต้องมีบันทึกที่กรองแล้ว 100 ล้านรายการต่อวัน สะสมดัชนีไว้ไม่ดีกว่าหรือ

การเพิ่มประสิทธิภาพการสืบค้น PostgreSQL เป็นกลุ่ม คิริลล์ โบโรวิคอฟ (เทนเซอร์)

หลังจากวิเคราะห์แผนทั้งหมดทีละโหนด เราพบว่ามีโครงสร้างทั่วไปบางอย่างในแผนที่มีแนวโน้มที่จะดูน่าสงสัย และเป็นการดีที่จะบอกนักพัฒนาว่า: "เพื่อนคุณอ่านดัชนีก่อนแล้วจึงเรียงลำดับแล้วตัดออก" - ตามกฎแล้วจะมีหนึ่งบันทึก

ทุกคนที่เขียนข้อความค้นหาอาจพบรูปแบบนี้: “ขอลำดับล่าสุดสำหรับ Vasya วันที่ของมัน” และหากคุณไม่มีดัชนีตามวันที่ หรือไม่มีวันในดัชนีที่คุณใช้ คุณจะ เหยียบ "คราด" แบบเดียวกันทุกประการ

แต่เรารู้ว่านี่คือ "คราด" - แล้วทำไมไม่บอกนักพัฒนาทันทีว่าเขาควรทำอย่างไร ดังนั้นเมื่อเปิดแผนในตอนนี้ นักพัฒนาของเราจะเห็นภาพที่สวยงามพร้อมคำแนะนำทันที โดยที่พวกเขาบอกเขาทันทีว่า “คุณมีปัญหาตรงนี้และตรงนั้น แต่พวกเขาได้รับการแก้ไขด้วยวิธีนี้และด้วยวิธีนี้”

ส่งผลให้จำนวนประสบการณ์ที่จำเป็นในการแก้ปัญหาตั้งแต่เริ่มต้นและตอนนี้ลดลงอย่างมาก นี่คือเครื่องมือประเภทที่เรามี

การเพิ่มประสิทธิภาพการสืบค้น PostgreSQL เป็นกลุ่ม คิริลล์ โบโรวิคอฟ (เทนเซอร์)

ที่มา: will.com

เพิ่มความคิดเห็น