คำอธิบายของ JSONB นำเสนอโดย PostgreSQL


346

PostgreSQL แนะนำเพียงJSONBและมันมีอยู่แล้วได้รับความนิยมในข่าวแฮ็กเกอร์ มันจะดีถ้ามีใครสามารถอธิบายได้ว่ามันแตกต่างจาก Hstore และ JSON ก่อนหน้านี้ใน PostgreSQL อะไรคือข้อดีและข้อ จำกัด ของมันและเมื่อมีคนควรพิจารณาใช้มัน?


4
จาก PGCon2014: youtube.com/…
msanford

5
@CraigRinger url ไม่แม่นยำพอตอนนี้ 1 ปีต่อมามันไม่ได้ชี้ให้ใกล้กับเนื้อหาที่เกี่ยวข้องกับ JSONB
berkus

2
@berkus ฉันคิดว่าฉันเชื่อมโยงกับโพสต์ที่เฉพาะเจาะจง น่าผิดหวังแค่ไหน
Craig Ringer

1
มันชี้ไปที่วิดีโอเฉพาะ
talonx

คำตอบ:


458

ก่อนอื่นhstoreเป็นโมดูล contrib ซึ่งอนุญาตให้คุณเก็บคู่ key => value เท่านั้นโดยที่คีย์และค่าสามารถเป็นtexts เท่านั้น(อย่างไรก็ตามค่าสามารถเป็น sql NULLได้เช่นกัน)

ทั้งjson& jsonbอนุญาตให้คุณเก็บค่า JSON ที่ถูกต้อง(กำหนดไว้ในข้อมูลจำเพาะ )

F.ex. เหล่านี้เป็นตัวแทน JSON ที่ถูกต้อง: null, true, [1,false,"string",{"foo":"bar"}], {"foo":"bar","baz":[null]}- hstoreเป็นเพียงส่วนย่อยเล็ก ๆ น้อย ๆ เมื่อเทียบกับสิ่งที่มีความสามารถ JSON ( แต่ถ้าคุณต้องการเพียงเซตนี้ก็ปรับ)

ข้อแตกต่างระหว่างjson& jsonbคือที่เก็บข้อมูล:

  • json จะถูกจัดเก็บในรูปแบบข้อความธรรมดาในขณะที่
  • jsonb ถูกเก็บไว้ในการเป็นตัวแทนไบนารี

มี 3 ผลกระทบที่สำคัญของสิ่งนี้:

  • jsonb มักจะใช้พื้นที่ดิสก์ในการจัดเก็บมากกว่า json (บางครั้งไม่)
  • jsonb ใช้เวลาในการสร้างมากขึ้นจากการเป็นตัวแทนอินพุตมากกว่า json
  • jsonการดำเนินการใช้เวลาอย่างมีนัยสำคัญมากกว่าjsonb(& การแยกวิเคราะห์ยังต้องทำทุกครั้งที่คุณดำเนินการบางอย่างด้วยjsonค่าที่พิมพ์)

เมื่อjsonbใดที่จะสามารถใช้งานได้กับรุ่นที่เสถียรจะมีสองกรณีการใช้งานที่สำคัญเมื่อคุณสามารถเลือกได้อย่างง่ายดาย:

  1. หากคุณทำงานกับการเป็นตัวแทน JSON ในแอปพลิเคชันของคุณ PostgreSQL จะถูกใช้เพื่อจัดเก็บและดึงข้อมูลการเป็นตัวแทนนี้เท่านั้นคุณควรใช้ jsonจะใช้เฉพาะในการจัดเก็บและเรียกการแสดงนี้คุณควรใช้
  2. ถ้าคุณทำมากของการดำเนินงานเกี่ยวกับค่า JSON ใน PostgreSQL หรือการใช้การจัดทำดัชนีในบางฟิลด์ JSON jsonbคุณควรใช้

1
สวัสดีเนื่องจากมันมีตัวแทนไบนารีทำไมjsonbไม่สนับสนุนสิ่งนี้ UPDATE test SET data->'a' = 123 WHERE id = 1;จากCREATE TABLE test(id SERIAL PRIMARY KEY, data JSONB);
Kokizzu

1
Kokizzu เป็นไปได้ใน 9.5 wiki.postgresql.org/wiki/…
ChelowekKot

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

4
เนื่องจากเหตุผลดั้งเดิม: ใน JSON ไม่มีความแตกต่างทางความหมายถ้าคู่ของคีย์ - ค่าของตาราง (แผนที่แม็กแฮชสิ่งที่เรียกในภาษาโฮสต์) ต่างกัน หากคุณพึ่งพาสิ่งนั้นจริง ๆ แล้วคุณกำลังใช้สิ่งที่แตกต่างจาก JSON - สำหรับtextvs. json: หลังมาพร้อมกับการตรวจสอบ JSON ดังนั้นเมื่อใช้ JSON ที่ไม่ถูกต้องมันจะล้มเหลวเมื่อทำการแทรกเท่านั้นแทนทุกครั้งที่แอปพลิเคชันของคุณอ่าน (เพราะได้รับการแสดงที่ไม่ถูกต้อง) นอกจากนี้คุณสามารถโยนหลังเพื่อjsonbภายในฐานข้อมูล
pozs

2
นี่เป็นบทความที่ยอดเยี่ยมเกี่ยวกับการอธิบายรายละเอียดการใช้งานสำหรับ JSONB ( pgeoghegan.blogspot.com/2014/03/what-i-think-of-jsonb.html )
manugupt1

132

Peeyush:

คำตอบสั้น ๆ คือ:

  • หากคุณกำลังทำ JSON อยู่ภายใน PostgreSQL เช่นการเรียงลำดับการแบ่งการต่อข้อมูล ฯลฯ คุณควรใช้ JSONB เพื่อเหตุผลด้านความเร็ว
  • หากคุณต้องการการค้นหาแบบดัชนีสำหรับการค้นหาคีย์โดยพลการบน JSON คุณควรใช้ JSONB
  • หากคุณไม่ทำตามข้างต้นคุณควรใช้ JSON
  • หากคุณต้องการรักษาการเรียงลำดับคีย์พื้นที่ว่างและคีย์ซ้ำคุณควรใช้ JSON

สำหรับคำตอบที่ยาวขึ้นคุณจะต้องรอให้ฉันเขียนบทความ "HowTo" ฉบับเต็มใกล้กับรุ่น 9.4


74

คำอธิบายอย่างง่ายเกี่ยวกับความแตกต่างระหว่าง json และ jsonb ( ภาพต้นฉบับโดย PostgresProfessional ):

SELECT '{"c":0,   "a":2,"a":1}'::json, '{"c":0,   "a":2,"a":1}'::jsonb;

          json          |        jsonb 
------------------------+--------------------- 
 {"c":0,   "a":2,"a":1} | {"a": 1, "c": 0} 
(1 row)
  • json: การจัดเก็บข้อมูลต้นฉบับ«ตามที่เป็น»
  • jsonb: ไม่มีช่องว่าง
  • jsonb: ไม่มีกุญแจที่ซ้ำกันชนะคีย์สุดท้าย
  • jsonb: คีย์ถูกเรียงลำดับ

เพิ่มเติมในวิดีโอคำพูดและการนำเสนอภาพนิ่งโดยนักพัฒนา jsonb นอกจากนี้พวกเขายังแนะนำJsQuery , pg.extension ให้ภาษาเคียวรี jsonb ที่ทรงพลัง


1
ขอบคุณฉันได้แทนที่เป็นข้อความ
ChelowekKot

56
  • hstore เป็นประเภทหน่วยเก็บข้อมูล "คอลัมน์กว้าง" มากกว่ามันเป็นพจนานุกรมแบบแบน (ไม่ซ้อนกัน) ของคู่คีย์ - ค่าซึ่งจัดเก็บในรูปแบบไบนารีที่มีประสิทธิภาพพอสมควรเสมอ (ตารางแฮชดังนั้นชื่อ)
  • jsonจัดเก็บเอกสาร JSON เป็นข้อความดำเนินการตรวจสอบความถูกต้องเมื่อจัดเก็บเอกสารและแยกวิเคราะห์เอกสารออกหากจำเป็น (เช่นการเข้าถึงแต่ละฟิลด์) ควรสนับสนุนข้อมูลจำเพาะ JSON ทั้งหมด เนื่องจากข้อความ JSON ทั้งหมดถูกจัดเก็บการจัดรูปแบบจะถูกเก็บไว้
  • jsonbใช้ทางลัดเพื่อเหตุผลด้านประสิทธิภาพ: ข้อมูล JSON จะถูกวิเคราะห์ในอินพุตและเก็บไว้ในรูปแบบไบนารีการเรียงลำดับคีย์ในพจนานุกรมจะไม่ได้รับการบำรุงรักษาและไม่มีคีย์ซ้ำกัน การเข้าถึงแต่ละองค์ประกอบในฟิลด์ JSONB นั้นรวดเร็วเนื่องจากไม่ต้องแยกวิเคราะห์ข้อความ JSON ตลอดเวลา บนเอาต์พุตข้อมูล JSON จะถูกสร้างขึ้นใหม่และการจัดรูปแบบเริ่มต้นจะหายไป

IMO ไม่มีเหตุผลสำคัญที่จะไม่ใช้jsonbเมื่อมีหากคุณกำลังทำงานกับข้อมูลที่เครื่องอ่านได้


24

JSONB เป็นรุ่น "ดีกว่า" ของ JSON

ลองดูตัวอย่าง:

SELECT '{"c":0,   "a":2,"a":1}'::json, '{"c":0,   "a":2,"a":1}'::jsonb;
          json          |        jsonb 
------------------------+--------------------- 
 {"c":0,   "a":2,"a":1} | {"a": 1, "c": 0} 
(1 row)
  1. JSON เก็บพื้นที่สีขาวนี่คือเหตุผลที่เราสามารถเห็นช่องว่างเมื่อคีย์ "a" ถูกเก็บไว้ในขณะที่ JSONB ไม่ได้
  2. JSON เก็บค่าทั้งหมดของคีย์ นี่คือเหตุผลที่คุณสามารถเห็นหลายค่า (2 และ 1) กับคีย์ "a" ในขณะที่ JSONB เท่านั้น "เก็บ" ค่าสุดท้าย
  3. JSON รักษาลำดับที่องค์ประกอบจะถูกแทรกในขณะที่ JSONB รักษาลำดับ "เรียง"
  4. วัตถุ JSONB จะถูกจัดเก็บเป็นไบนารีที่คลายการบีบอัดซึ่งตรงข้ามกับ "ข้อมูลดิบ" ใน JSON ซึ่งไม่จำเป็นต้องทำการวิเคราะห์ข้อมูลซ้ำระหว่างการดึงข้อมูล
  5. JSONB ยังรองรับการจัดทำดัชนีซึ่งอาจเป็นข้อได้เปรียบที่สำคัญ

โดยทั่วไปเราควรเลือก JSONB ยกเว้นว่ามีความต้องการเฉพาะเช่นสมมติฐานเกี่ยวกับการสั่งซื้อคีย์วัตถุ


13

ฉันอยู่ที่ pgopen วันนี้มาตรฐานเร็วกว่า mongodb ฉันเชื่อว่ามันเร็วกว่าประมาณ 500% สำหรับการเลือก ทุกอย่างสวยเร็วกว่าอย่างน้อย 200% เมื่อเทียบกับ mongodb มากกว่าหนึ่งข้อยกเว้นในขณะนี้คือการอัปเดตที่ต้องเขียนใหม่ทั้งหมดใน json คอลัมน์ทั้งหมดที่ mongodb จัดการได้ดีกว่า

การจัดทำดัชนีจินบน jsonb ฟังดูน่าทึ่ง

นอกจากนี้ postgres จะยังคงประเภทของ jsonb ภายในและโดยทั่วไปจะจับคู่กับประเภทเช่นตัวเลขข้อความบูลีน ฯลฯ

เข้าร่วมก็จะเป็นไปได้โดยใช้ jsonb

เพิ่ม PLv8 สำหรับขั้นตอนการจัดเก็บและนี่จะเป็นความฝันที่เป็นจริงสำหรับนักพัฒนา node.js

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

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


8

เกี่ยวกับความแตกต่างระหว่างjsonและjsonbประเภทข้อมูลมีมูลค่าการกล่าวถึงคำอธิบายอย่างเป็นทางการ:

PostgreSQL มีสองประเภทสำหรับการจัดเก็บข้อมูล JSON: และjson jsonbในการใช้กลไกการสืบค้นที่มีประสิทธิภาพสำหรับประเภทข้อมูลเหล่านี้ PostgreSQL ยังจัดเตรียมชนิดข้อมูล jsonpath ที่อธิบายไว้ในส่วน 8.14.68.14.6

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

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

โดยทั่วไปแอปพลิเคชันส่วนใหญ่ควรเก็บข้อมูล JSON เป็น jsonbเว้นแต่มีความต้องการค่อนข้างพิเศษเช่นสมมติฐานดั้งเดิมเกี่ยวกับการสั่งซื้อคีย์วัตถุ

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

ที่มา: https://www.postgresql.org/docs/current/datatype-json.html


7

ข้อแตกต่างที่สำคัญอีกข้อหนึ่งที่ไม่ได้กล่าวถึงในคำตอบข้างต้นคือไม่มีตัวดำเนินการความเสมอภาคสำหรับjsonประเภท แต่มีสำหรับjsonbแต่มีหนึ่งสำหรับ

ซึ่งหมายความว่าคุณไม่สามารถใช้DISTINCTคำหลักเมื่อเลือกjson-type และ / หรือฟิลด์อื่น ๆ จากตาราง (คุณสามารถใช้DISTINCT ONแทนได้ แต่อาจไม่สามารถทำได้เนื่องจากทุกกรณีเช่นนี้ )


6

เท่าที่ฉันสามารถบอกได้

  • hstore เนื่องจากมีอยู่ในปัจจุบัน (ใน Postgresql 9.3) ไม่อนุญาตให้ซ้อนวัตถุและอาร์เรย์อื่น ๆ เป็นค่าของคู่คีย์ / ค่า อย่างไรก็ตามแพทช์ hstore ในอนาคตจะอนุญาตให้ทำรังได้ โปรแกรมปรับปรุงนี้จะไม่อยู่ในรุ่น 9.4 และอาจไม่รวมในเวลาไม่นาน

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

  • jsonb ที่จะวางจำหน่ายใน 9.4 จะมีความสามารถในการซ้อนปัจจุบันของ json เช่นเดียวกับการทำดัชนี GIN / GIST ของ hstore ดังนั้นมันจะเร็ว

คนที่ทำงานกับ postgresql 9.4 ดูเหมือนจะบอกว่าประเภท jsonb ใหม่ที่รวดเร็วจะดึงดูดผู้ที่เลือกใช้ noSQL data store เช่น MongoDB แต่ตอนนี้สามารถรวมฐานข้อมูลเชิงสัมพันธ์กับข้อมูลที่ไม่มีโครงสร้างที่สามารถสืบค้นได้ภายใต้หลังคาเดียวกัน

http://www.databasesoup.com/2014/02/why-hstore2jsonb-is-most-important.html

มาตรฐานของ postgresql 9.4 jsonb ดูเหมือนจะเทียบเท่าหรือในบางกรณีเร็วกว่า MongoDB

http://texture.io/alphabetum/postgresql-incl-hstore-vs-mongodb

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.