PostgreSQL: ไม่เปลี่ยนรูปเปลี่ยนแปลงได้เสถียร


11

ฉันไม่ชัดเจนเกี่ยวกับความหมายที่แท้จริงในคำจำกัดความของฟังก์ชัน IMMUTABLE, VOLATILE และ STABLE

ฉันอ่านเอกสารโดยเฉพาะคำจำกัดความของแต่ละคำ

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

STABLE บ่งชี้ว่าฟังก์ชั่นไม่สามารถแก้ไขฐานข้อมูลและภายในการสแกนตารางเดียวมันจะส่งคืนผลลัพธ์เดียวกันสำหรับค่าอาร์กิวเมนต์เดียวกันแต่ผลลัพธ์นั้นสามารถเปลี่ยนแปลงได้ตลอดทั้งคำสั่ง SQL นี่คือการเลือกที่เหมาะสมสำหรับฟังก์ชั่นที่ผลลัพธ์ขึ้นอยู่กับการค้นหาฐานข้อมูลตัวแปรพารามิเตอร์ (เช่นเขตเวลาปัจจุบัน) ฯลฯ (ไม่เหมาะสมสำหรับทริกเกอร์ AFTER ที่ต้องการแถวการสืบค้นที่แก้ไขโดยคำสั่งปัจจุบัน) โปรดทราบว่า ฟังก์ชันตระกูล current_timestamp มีคุณสมบัติว่าเสถียรเนื่องจากค่าของมันไม่เปลี่ยนแปลงภายในธุรกรรม

VOLATILE บ่งชี้ว่าค่าฟังก์ชั่นสามารถเปลี่ยนแปลงได้แม้ในการสแกนตารางเดียวดังนั้นจึงไม่มีการปรับให้เหมาะสม ฟังก์ชันฐานข้อมูลค่อนข้างน้อยมีความผันผวนในแง่นี้ ตัวอย่างบางส่วนเป็นแบบสุ่ม (), currval (), timeofday () แต่โปรดทราบว่าฟังก์ชั่นใด ๆ ที่มีผลข้างเคียงจะต้องจำแนกความผันผวนแม้ว่าผลที่ได้นั้นจะสามารถคาดเดาได้อย่างชัดเจนเพื่อป้องกันการโทรออก ตัวอย่างคือ setval ()

ความสับสนของฉันมาพร้อมกับเงื่อนไขสำหรับ IMMUTABLE และเสถียรที่ฟังก์ชันALWAYSหรือCONSISTENTLYส่งคืนผลลัพธ์เดียวกันโดยให้อาร์กิวเมนต์เดียวกัน

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

ด้วย STABLE คำจำกัดความจะคล้ายกันกับที่บอกว่าควรให้ผลลัพธ์ที่เหมือนกัน ดังนั้นสำหรับฉันนั่นหมายความว่าทุกครั้งที่ฟังก์ชั่นถูกเรียกด้วยอาร์กิวเมนต์เดียวกันมันควรส่งคืนผลลัพธ์เดียวกัน (แถวที่แน่นอนเหมือนกันทุกครั้ง)

ดังนั้นสำหรับฉัน ... นั่นหมายความว่าฟังก์ชั่นใด ๆ ที่ทำงานบน SELECT ในตารางหรือตารางที่สามารถอัพเดตได้ควรจะเปลี่ยนแปลงได้ง่าย

แต่อีกครั้ง ... ที่ไม่ถูกต้องสำหรับฉัน

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

นั่นหมายความว่าหน้าที่ของฉันควรเป็น VOLATILE หรือไม่ แม้ว่าเอกสารระบุว่าฟังก์ชันฐานข้อมูลค่อนข้างน้อยมีความผันผวนในแง่นี้หรือไม่?

ขอบคุณ!

คำตอบ:


15

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

STABLEสามารถใช้อินพุตที่เป็นของตัวเองSTABLE: อื่น ๆSTABLEหรือIMMUTABLEฟังก์ชั่นและSELECTแบบสอบถามของตาราง มีความปลอดภัยในการสืบค้นตารางเนื่องจากมุมมองของฟังก์ชั่นของตารางเหล่านั้นจะไม่เปลี่ยนแปลงภายในภาพรวมปัจจุบันของแบบสอบถาม คุณสามารถเข้าถึงค่า GUC ( current_setting(...)) ตราบใดที่คุณรู้ว่าจะไม่ได้รับมอบหมายให้ภายในคำสั่งปัจจุบัน

VOLATILE ฟังก์ชั่นคือทุกสิ่งที่ไม่พอดีกับด้านบน:

  • อะไรก็ได้ที่มีผลข้างเคียง
  • สิ่งที่เขียน
  • สิ่งใดก็ตามที่สืบค้นข้อมูลภายนอกที่ไม่ได้จัดการโดยสแน็ปช็อต PostgreSQL
  • ...

โดยทั่วไปเพียงแค่ปล่อยให้ทุกสิ่งทุกอย่างVOLATILEเว้นแต่คุณจะมีเหตุผลที่ดีที่จะไม่ทำ

เหตุผลหลักที่ใช้IMMUTABLEคือเมื่อเขียนฟังก์ชั่นที่จะใช้เป็นส่วนหนึ่งของการแสดงออกของดัชนี


1
"พวกเขาไม่สามารถเข้าถึงตาราง" ในความเป็นธรรมพวกเขาสามารถและพวกเขาทำ ฉันคิดว่ากฎทั่วไปมากขึ้นคือตารางไม่ควรมีความหมายกลายพันธุ์โดยไม่ต้องรีสตาร์ทฐานข้อมูล
Evan Carroll

หาก STABLE อนุญาตให้เข้าถึงตารางมีการเพิ่มประสิทธิภาพมากกว่า / สูงกว่า VOLATILE ... หรือไม่
Brooks

อย่าลืมด้านบนของหัวของฉันจะต้องตรวจสอบเอกสาร / รหัส
Craig Ringer

4

สำหรับเสถียรส่วนที่คุณต้องใช้ตัวหนาคือ 'ผลลัพธ์อาจเปลี่ยนแปลงได้ตลอดทั้งคำสั่ง SQL'

สิ่งที่ไม่ควรเปลี่ยนแปลง แม้ว่าคุณจะรีสตาร์ทเซิร์ฟเวอร์ฐานข้อมูลของคุณวิ่งyum update( แต่แน่นอนอาจมีข้อผิดพลาด!) เปลี่ยนการตั้งค่าของคุณ (เช่นdatestyle, timezone, default_text_search_config, extra_float_digitsฯลฯ ) หรือเปลี่ยนฮาร์ดแวร์เซิร์ฟเวอร์ทั้งหมด (ของสถาปัตยกรรมเช่นเดียวกับฮาร์ดแวร์เก่าดังนั้น ไฟล์ไบนารียังคงใช้งานร่วมกันได้)

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


ฉันเชื่อว่าฉันเข้าใจสิ่งที่จำเป็นต้องมีก่อนสำหรับ IMMUTABLE (ไม่มีสิ่งใดที่สามารถเปลี่ยนแปลงได้ .... ตลอดเวลาระหว่างการค้นหาการเชื่อมต่อการเรียบใหม่การทำลายของดาวเคราะห์และการสร้างใหม่แม้จะมีการแก้ไขฐานข้อมูล) และ VOLATILE ซึ่งมันถูกเรียกว่า) ถูกต้องหรือไม่ ดังนั้นจากนั้นจะปรากฏเสถียรเพียงหมายความว่าฟังก์ชั่นไม่ได้แก้ไขฐานข้อมูลและไม่สามารถเข้าถึงฐานข้อมูลนอกบริบทของมันได้หรือไม่ คำจำกัดความของ STABLE ให้ความรู้สึกเหมือนว่ามันซับซ้อนกว่าที่จำเป็นจริงๆ ... หรือฉันจะละทิ้งบางอย่าง
Brooks

PostgreSQL จริง ๆ แล้วมีปัญหาบางอย่างรอบตัวIMMUTABLEและ collations มันเชื่อมั่นว่าglibc(หรือใน Pg ใหม่, iconv) จะไม่เปลี่ยนนิยามการเรียงหน้า ในความเป็นจริงพวกเขาทำและไม่สามารถตรวจจับการเปลี่ยนแปลงดังกล่าวได้ มันจะนำไปสู่การทุจริตดัชนีเงียบ :( มันเป็นส่วนใหญ่ปัญหาเมื่อจำลองระหว่างรุ่น OS ที่แตกต่างกัน ฯลฯ .
เครก Ringer
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.