การจัดเก็บข้อมูลใน MySQL เป็น JSON


121

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

โดยทั่วไปแล้วสถานที่ที่ดีในการเรียนรู้วิธีจัดเก็บทุกอย่างใน MySQL เป็นฐานข้อมูล CouchDB คืออะไร? การจัดเก็บทุกอย่างเป็น JSON ดูเหมือนว่าจะง่ายและรวดเร็วกว่า (ไม่ใช่การสร้างความหน่วงแฝงน้อยลง)

นอกจากนี้การแก้ไขลบ ฯลฯ สิ่งที่จัดเก็บเป็น JSON บน DB ยังทำได้ง่ายหรือไม่


สำหรับการอ้างอิงฉันเชื่อว่านี่เป็นการสนทนาของ FriendFeed เกี่ยวกับการใช้ JSON ใน MySQL: backchannel.org/blog/friendfeed-schemaless-mysql
dimo414

10
MySQL 5.7 รองรับพื้นที่เก็บข้อมูล JSON ดั้งเดิมแล้ว
eecue

คำตอบ:


57

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

อย่า

ต้องบอกว่า FriendFeed ดูเหมือนจะใช้สคีมาที่กำหนดเองอย่างมากกับ MySQL ขึ้นอยู่กับสิ่งที่คุณต้องการจัดเก็บจริงๆแทบจะไม่มีคำตอบที่ชัดเจนเกี่ยวกับวิธีการใช้ระบบฐานข้อมูลในทางที่ผิดดังนั้นจึงเหมาะสมสำหรับคุณ เนื่องจากบทความนี้เก่ามากและเหตุผลหลักของพวกเขาในการต่อต้าน Mongo และ Couch นั้นยังไม่บรรลุนิติภาวะฉันจะประเมินสองสิ่งนี้อีกครั้งหาก MySQL ไม่ได้ตัดให้คุณ พวกเขาน่าจะเติบโตขึ้นมากในตอนนี้


3
ใช่ฉันกำลังดู Mongo และ php มีส่วนขยายสำหรับมันและไวยากรณ์จริงสำหรับธุรกรรม DB ดูเหมือนง่ายกว่า MySQL และการทำงานโดยรวมดูเหมือนว่า couchDB จะง่ายกว่า ขอบคุณฉันคิดว่าฉันจะไปกับ MongoDB :)
Oscar Godson

68
มีกรณีที่ถูกต้องสำหรับการจัดเก็บ JSON blobs ใน RDBMS หากคุณเพียงแค่ต้องการจัดเก็บและดึงข้อมูล JSON แบบทึบแสงโดยไม่จำเป็นต้องค้นหาข้อมูลนั้นซึ่งเกิดขึ้นค่อนข้างบ่อยในบางสถานการณ์คุณอาจทำได้ดีมาก
markus

9
@markus ฉันทำสิ่งนี้ในเว็บไซต์หนึ่งของฉันโดยเฉพาะฟิลด์ของรูปแบบที่ซับซ้อนซึ่งไม่เคยค้นหาโดยตรงในแบบสอบถาม MySQL แต่ใช้เมื่อดูแบบฟอร์ม (ไม่ว่าจะจากมุมมองตารางหรือโดยตรงผ่านลิงก์) อาจไม่เหมาะอย่างยิ่ง แต่ก็ทำให้การนำไปใช้งานได้เร็วขึ้นมากและขจัดความจำเป็นในการใช้ตารางหรือคอลัมน์ตารางจำนวนมากเกินไป
Nick Bedford

1
หากคุณต้องการมีทั้ง RDBMS และที่เก็บข้อมูลประเภทเอกสารสำหรับแอปพลิเคชันของคุณนี่เป็นแนวทางที่ดีดังนั้นคุณจึงไม่ต้องการจัดการฐานข้อมูลหลาย ๆ
rjarmstrong

5
นี่เป็นคำแนะนำสั้น ๆ ซึ่งอาจเป็นเพราะคนที่ใช้เวลาในการแลกเปลี่ยนกองซ้อนมากเกินไป? เมื่อฉันมีเรกคอร์ดที่มี 100 ฟิลด์ที่ฉันต้องการจัดเก็บและฉันต้องการค้นหาใน 3 หรือ 4 ฟิลด์เท่านั้นการสร้างตารางที่มี 100 ฟิลด์นั้นเป็นเรื่องไร้สาระ คุณสามารถจัดเก็บบันทึกลูกค้าด้วยสมุดรายชื่อทั้งหมดของเขาที่เก็บไว้ใน 1 ช่องใน JSON และเพียงแค่เพิ่มรหัสลูกค้านามสกุล บริษัท เป็นช่องอื่น ๆ เพื่อใช้ในการค้นหาบันทึก มันเป็น. ประหยัดเวลาได้มาก
Danial

102

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

วิธีที่ดีที่สุดในการทำเช่นนี้คือการใช้ข้อมูลแบบไฮบริดเช่นหากคุณต้องการค้นหาตามวันที่เวลา MySQL (ปรับแต่งประสิทธิภาพ) จะเร็วกว่า PHP มากและสำหรับบางอย่างเช่นระยะทางการค้นหาของสถานที่ MySQL ก็ควรมีมากเช่นกัน เร็วขึ้น (สังเกตว่าค้นหาไม่เข้าถึง) ข้อมูลที่คุณไม่จำเป็นต้องค้นหาสามารถเก็บไว้ใน JSON, BLOB หรือรูปแบบอื่น ๆ ที่คุณเห็นว่าจำเป็นจริงๆ

ข้อมูลที่คุณต้องการเข้าถึงจะถูกจัดเก็บเป็น JSON ได้ง่ายมากเช่นระบบใบแจ้งหนี้พื้นฐานต่อกรณี พวกเขาไม่ได้รับประโยชน์มากนักจาก RDBMS และสามารถเก็บไว้ใน JSON เพียงแค่ json_encoding ($ _ POST ['entires']) หากคุณมีโครงสร้างรูปแบบ HTML ที่ถูกต้อง

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


8
-1 สำหรับ "การจัดเก็บโค้ด JSON ผ่าน PHP ในฐานข้อมูลเชิงสัมพันธ์ทำได้ดี" - การจัดเก็บ JSON (ซึ่งสามารถแสดงเอนทิตีทั้งหมดเป็นข้อมูลที่ไม่ใช่อะตอม) ในฟิลด์เดียวจะละเมิดโมเดลเชิงสัมพันธ์และป้องกัน 1NF นอกจากนี้อย่าอ้างสิทธิ์ในวงกว้างเกี่ยวกับประสิทธิภาพโดยไม่มีเมตริกให้คุณสำรองข้อมูล
Sage Gerard

80
ตามที่กล่าวไว้ขึ้นอยู่กับสิ่งที่คุณจัดเก็บกล่าวคือสำหรับใบแจ้งหนี้คุณจำเป็นต้องจัดเก็บแต่ละรายการแยกกันหรือไม่? ไม่ความคิดเห็นของคุณเป็นเหมือนที่คุณรู้มาก แต่ 1NF ไม่ได้มีไว้สำหรับทุกฟิลด์หรือจะไม่มี BLOB และประเภทข้อความ ... นี่เป็นเรื่องไร้สาระอย่างแท้จริงสำหรับระบบการผลิตคุณจะต้องปรับแต่งสิ่งที่คุณต้องการค้นหาจาก เช่นวันที่คีย์และตั้งค่าดัชนีในข้อมูลบางอย่าง ฉันไม่ได้บอกว่าเก็บทุกอย่างเป็น JSON ฉันบอกว่าจัดเก็บข้อมูลบางส่วนเป็น JSON หากช่วยแก้ปัญหาของคุณได้
Lewis Richard Phillip Cowles

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

29
คุณสมมติว่าฉันไม่ได้ปรึกษากับ DBA เกี่ยวกับปัญหานี้และไม่เข้าใจสิ่งที่คุณกำลังพูด ฉันไม่ได้อยู่ในวงรอบว่าความหมายของสิ่งนี้คืออะไรทั้งสำหรับระบบขนาดเล็กและต่อไปอีกขั้น แต่สิ่งที่ฉันกำลังพูดคือคุณคิดผิดและงานวิจัยที่คุณชี้ไปนั้นเก่าและไม่ได้ใช้แอปพลิเคชันของเรา กลยุทธ์. มันผิดธรรมดาและปัญหาน้ำด่างในการใช้กระบวนการนี้ไม่ดี ตัวอย่างเช่นฉันไม่ได้บอกว่ามีเพียงรุ่นเดียวหรือไม่ใช้ RDBMS ฉันกำลังบอกว่าคุณต้องฉลาดเกี่ยวกับตำแหน่งที่คุณใช้ RDBMS และที่ที่คุณไม่จำเป็นต้องทำ
Lewis Richard Phillip Cowles

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

72

MySQL 5.7 ตอนนี้รองรับประเภทข้อมูล JSON ดั้งเดิมที่คล้ายกับ MongoDB และที่เก็บข้อมูลเอกสารแบบไม่ใช้สคีมาอื่น ๆ :

การสนับสนุน JSON

เริ่มต้นด้วย MySQL 5.7.8 MySQL รองรับประเภท JSON ดั้งเดิม ค่า JSON จะไม่ถูกจัดเก็บเป็นสตริงแทนที่จะใช้รูปแบบไบนารีภายในที่อนุญาตให้เข้าถึงองค์ประกอบเอกสารได้อย่างรวดเร็ว เอกสาร JSON ที่จัดเก็บในคอลัมน์ JSON จะได้รับการตรวจสอบความถูกต้องโดยอัตโนมัติทุกครั้งที่มีการแทรกหรืออัปเดตเอกสารที่ไม่ถูกต้องทำให้เกิดข้อผิดพลาด เอกสาร JSON ถูกทำให้เป็นมาตรฐานในการสร้างและสามารถเปรียบเทียบได้โดยใช้ตัวดำเนินการเปรียบเทียบส่วนใหญ่เช่น =, <, <=,>,> =, <>,! = และ <=>; สำหรับข้อมูลเกี่ยวกับตัวดำเนินการที่สนับสนุนตลอดจนลำดับความสำคัญและกฎอื่น ๆ ที่ MySQL ปฏิบัติตามเมื่อเปรียบเทียบค่า JSON โปรดดูการเปรียบเทียบและการจัดลำดับค่า JSON

MySQL 5.7.8 ยังแนะนำฟังก์ชันต่างๆสำหรับการทำงานกับค่า JSON ฟังก์ชันเหล่านี้รวมถึงที่ระบุไว้ที่นี่:

  1. ฟังก์ชันที่สร้างค่า JSON: JSON_ARRAY (), JSON_MERGE () และ JSON_OBJECT () ดูส่วน 12.16.2“ ฟังก์ชันที่สร้างค่า JSON”
  2. ฟังก์ชันที่ค้นหาค่า JSON: JSON_CONTAINS (), JSON_CONTAINS_PATH (), JSON_EXTRACT (), JSON_KEYS () และ JSON_SEARCH () ดูหัวข้อ 12.16.3“ ฟังก์ชันที่ค้นหาค่า JSON”
  3. ฟังก์ชันที่แก้ไขค่า JSON: JSON_APPEND (), JSON_ARRAY_APPEND (), JSON_ARRAY_INSERT (), JSON_INSERT (), JSON_QUOTE (), JSON_REMOVE (), JSON_REPLACE (), JSON_SET () และ JSON_UNQUOTE () ดูหัวข้อ 12.16.4“ ฟังก์ชันที่ปรับเปลี่ยนค่า JSON”
  4. ฟังก์ชันที่ให้ข้อมูลเกี่ยวกับค่า JSON: JSON_DEPTH (), JSON_LENGTH (), JSON_TYPE () และ JSON_VALID () ดูส่วน 12.16.5“ ฟังก์ชันที่ส่งคืนแอตทริบิวต์ค่า JSON”

ใน MySQL 5.7.9 และใหม่กว่าคุณสามารถใช้ column-> path เป็นชวเลขสำหรับ JSON_EXTRACT (คอลัมน์เส้นทาง) สิ่งนี้ทำงานเป็นนามแฝงสำหรับคอลัมน์ที่ตัวระบุคอลัมน์สามารถเกิดขึ้นได้ในคำสั่ง SQL รวมถึงคำสั่ง WHERE, ORDER BY และ GROUP BY ซึ่งรวมถึงคำสั่ง SELECT, UPDATE, DELETE, CREATE TABLE และคำสั่ง SQL อื่น ๆ ด้านซ้ายมือต้องเป็นตัวระบุคอลัมน์ JSON (ไม่ใช่นามแฝง) ทางขวามือคือนิพจน์พา ธ JSON ที่ยกมาซึ่งประเมินเทียบกับเอกสาร JSON ที่ส่งคืนเป็นค่าคอลัมน์

ดูหัวข้อ 12.16.3“ ฟังก์ชันที่ค้นหาค่า JSON” สำหรับข้อมูลเพิ่มเติมเกี่ยวกับ -> และ JSON_EXTRACT () สำหรับข้อมูลเกี่ยวกับการสนับสนุนเส้นทาง JSON ใน MySQL 5.7 โปรดดูที่การค้นหาและแก้ไขค่า JSON ดูเพิ่มเติมดัชนีรองและคอลัมน์ที่สร้างขึ้นเสมือน

ข้อมูลเพิ่มเติม:

https://dev.mysql.com/doc/refman/5.7/en/json.html


26

อักขระ json ไม่มีอะไรพิเศษเมื่อพูดถึงพื้นที่จัดเก็บตัวอักษรเช่น

{, }, [, ], ', a-z, 0-9.... จริงๆไม่มีอะไรพิเศษและสามารถเก็บไว้เป็นข้อความ

ปัญหาแรกที่คุณจะต้องเจอคือปัญหานี้

{profile_id: 22, ชื่อผู้ใช้: 'Robert', รหัสผ่าน: 'skhgeeht893htgn34ythg9er'}

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

UPDATE users SET JSON(user_data,'username') = 'New User';

ในขณะที่คุณไม่สามารถทำได้คุณจะต้องเลือก json ก่อนถอดรหัสเปลี่ยนแปลงอัปเดตดังนั้นในทางทฤษฎีคุณอาจใช้เวลามากขึ้นในการสร้างโครงสร้างฐานข้อมูลที่เหมาะสม!

ฉันใช้ json ในการจัดเก็บข้อมูล แต่มีเพียง Meta Data ข้อมูลที่ไม่ได้รับการอัปเดตบ่อยครั้งไม่เกี่ยวข้องกับผู้ใช้โดยเฉพาะ .. ตัวอย่างเช่นหากผู้ใช้เพิ่มโพสต์และในโพสต์นั้นเขาเพิ่มรูปภาพที่ไม่สามารถแยกวิเคราะห์รูปภาพและสร้างนิ้วหัวแม่มือและ จากนั้นใช้ thumb urls ในรูปแบบ json


การจัดเก็บสตริง json ในฐานข้อมูลดีพอหรือไม่เมื่อฉันไม่อัปเดตเลย ฉันแค่ต้องการค้นหาตามปกติในข้อมูล json โดยใช้ LIKE ฉันเห็นว่าแม้แต่ Wordpress ยังเก็บข้อมูลเมตาของปลั๊กอินเป็นสตริง json ในฐานข้อมูล
shasi kanth

@shasikanth หากคุณกำลังค้นหาค่าในข้อมูล JSON ฉันจะมองหาแนวทางที่ดีกว่า
Kirby

15

เพื่อแสดงให้เห็นว่าการรับข้อมูล JSON โดยใช้แบบสอบถามนั้นยากเพียงใดฉันจะแชร์แบบสอบถามที่ฉันสร้างขึ้นเพื่อจัดการกับสิ่งนี้

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

SELECT
    SUBSTRING(
        REPLACE(REPLACE(REPLACE(column, '{', ''), '}', ','), '"', ''),
        LOCATE(
            CONCAT('myfield', ':'),
            REPLACE(REPLACE(REPLACE(column, '{', ''), '}', ','), '"', '')
        ) + CHAR_LENGTH(CONCAT('myfield', ':')),
        LOCATE(
            ',',
            SUBSTRING(
                REPLACE(REPLACE(REPLACE(column, '{', ''), '}', ','), '"', ''),
                LOCATE(
                    CONCAT('myfield', ':'),
                    REPLACE(REPLACE(REPLACE(column, '{', ''), '}', ','), '"', '')
                ) + CHAR_LENGTH(CONCAT('myfield', ':'))
            )
        ) - 1
    )
    AS myfield
FROM mytable WHERE id = '3435'

5
คุณจะไม่สอบถามฝั่งเซิร์ฟเวอร์นี้ นี่จะเป็นการจัดเก็บหยดและนำมันกลับฝั่งไคลเอ็นต์ จากนั้นคุณก็ใช้ JS เพื่อค้นหา นี่เป็นเวลานานแล้ว :) ตั้งแต่นั้นมาฉันได้ย้ายไปที่ MongoDB สำหรับสิ่งนี้ :) โหวตให้กับข้อความค้นหาที่เรียบเนียนนี้
Oscar Godson

ฉันคิดว่าเป็นคำถามที่ว่าบุคคลนั้นจะเข้าถึงข้อมูล JSON นั้นเป็นประจำหรือไม่ ตัวอย่างเช่นฉันกำลังย้ายส่วนหัวที่ไม่จำเป็นไปยังอาร์เรย์แยกวิเคราะห์เป็น JSON แล้วจัดเก็บ เมื่อฉันจะเรียกข้อมูล JSON (สำหรับคำขอ AJAX ส่วนหัวพิเศษที่หายาก) ฉันจะดึงจาก MySQL อ่าน JSON ในอาร์เรย์และสะท้อนส่วนหัวออก สำหรับข้อมูลที่เข้มข้นมากขึ้นอาจไม่ควรจัดเก็บเป็น JSON
John

10

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

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


2
ความคิดของฉันตรง หากข้อมูลที่ไม่เคยเข้าร่วม / ค้นหาหรือแม้แต่ไม่ค่อยได้รับการอัปเดตทำไมไม่ใช้ json ในฟิลด์ TEXT ตัวอย่างที่ดีคือตารางรายการอาหารที่รายการอาหารแต่ละรายการจะต้องจัดเก็บข้อมูลทางโภชนาการ ขนาดที่ให้บริการโปรเตียนคาร์โบไฮเดรตไขมันรวมไขมัน sat เป็นต้น แต่ไม่เพียงแค่นั้นคุณจะต้องเก็บค่า (0.2) และหน่วยที่วัดเป็น (g, oz, fl oz, ml) พิจารณาว่าเป็นข้อมูลที่ (ขึ้นอยู่กับสิ่งที่คุณกำลังทำฉันเดา) ไม่จำเป็นต้องค้นหาในฉันจะบอกว่า 1 TEXT เทียบกับ 16 คอลัมน์ int / varchar / enum เป็นการแลกเปลี่ยนที่ดี
Brad Moore

แน่นอน !!! มีประโยชน์เมื่อคุณต้องจัดเก็บตัวแปรและ / หรือโครงสร้างข้อมูลที่ไม่รู้จักซึ่งคุณไม่ได้วางแผนที่จะกรองด้วย SQL เลย ข้อมูลจะถูกจัดเก็บตามที่เป็นอยู่และคนอื่น (รหัสแอป) อาจรู้โครงสร้างและจะทำอย่างไรกับมัน
Delmo

9

นี่เป็นคำถามเก่า แต่ฉันยังสามารถเห็นคำถามนี้ได้ที่ด้านบนสุดของผลการค้นหาของ Google ดังนั้นฉันคิดว่าการเพิ่มคำตอบใหม่ 4 ปีหลังจากที่คำถามนั้นมีความหมาย

ก่อนอื่นมีการสนับสนุนที่ดีกว่าในการจัดเก็บ JSON ใน RDBMS คุณอาจพิจารณาเปลี่ยนไปใช้ PostgreSQL (แม้ว่า MySQL จะรองรับ JSON ตั้งแต่ v5.7.7) PostgreSQL ใช้คำสั่ง SQL ที่คล้ายกันมากกับ MySQL ยกเว้นว่าจะรองรับฟังก์ชันเพิ่มเติม หนึ่งในฟังก์ชันที่เพิ่มเข้ามาคือมีประเภทข้อมูล JSON และคุณสามารถสืบค้น JSON ที่จัดเก็บไว้ได้แล้ว ( อ้างอิงบางส่วนเกี่ยวกับเรื่องนี้ ) หากคุณไม่ได้สร้างแบบสอบถามโดยตรงในโปรแกรมของคุณตัวอย่างเช่นใช้ PDO ใน php หรือพูดเก่งใน Laravel สิ่งที่คุณต้องทำก็เพียงแค่ติดตั้ง PostgreSQL บนเซิร์ฟเวอร์ของคุณและเปลี่ยนการตั้งค่าการเชื่อมต่อฐานข้อมูล คุณไม่จำเป็นต้องเปลี่ยนรหัสของคุณ

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

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

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

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


8

ฉันจะบอกว่าเหตุผลสองประการที่ควรพิจารณาคือ:

  • ประสิทธิภาพไม่ดีพอสำหรับแนวทางที่เป็นมาตรฐาน
  • คุณไม่สามารถสร้างแบบจำลองข้อมูลที่ลื่นไหล / ยืดหยุ่น / เปลี่ยนแปลงโดยเฉพาะของคุณได้อย่างง่ายดาย

ฉันเขียนเกี่ยวกับแนวทางของตัวเองที่นี่:

คุณพบปัญหาความสามารถในการปรับขนาดใดบ้างเมื่อใช้ที่เก็บข้อมูล NoSQL

(ดูคำตอบด้านบน)

แม้แต่ JSON ก็ยังไม่เร็วพอเราจึงใช้วิธีกำหนดรูปแบบข้อความ ทำงานแล้ว / ยังคงทำงานได้ดีสำหรับเรา

มีเหตุผลที่คุณไม่ใช้ MongoDB หรือไม่? (อาจเป็น MySQL "จำเป็น" เพียงแค่อยากรู้)


6

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

ในปี 2014 เราสามารถเข้าถึงเซิร์ฟเวอร์ฐานข้อมูลจำนวนมากที่จัดการข้อมูลบางประเภทได้ดีเป็นพิเศษ

  • Mongo (ที่เก็บเอกสาร)
  • Redis (การจัดเก็บข้อมูลคีย์ - ค่า)
  • MySQL / Maria / PostgreSQL / Oracle / etc (ข้อมูลเชิงสัมพันธ์)
  • CouchDB (JSON)

ฉันแน่ใจว่าฉันพลาดคนอื่น ๆ เช่น RabbirMQ และ Cassandra ประเด็นของฉันคือใช้เครื่องมือที่เหมาะสมสำหรับข้อมูลที่คุณต้องการจัดเก็บ

หากแอปพลิเคชันของคุณต้องการการจัดเก็บและการดึงข้อมูลที่หลากหลายจริงๆเร็วมาก (และใครไม่) ก็อย่าอายที่จะใช้แหล่งข้อมูลหลายแหล่งสำหรับแอปพลิเคชัน เว็บเฟรมเวิร์กยอดนิยมให้การสนับสนุนแหล่งข้อมูลหลายแหล่ง (Rails, Django, Grails, Cake, Zend และอื่น ๆ ) กลยุทธ์นี้จำกัดความซับซ้อนไว้ที่พื้นที่เฉพาะของแอปพลิเคชัน ORM หรืออินเทอร์เฟซแหล่งข้อมูลของแอปพลิเคชัน


1
ในความคิดของคุณ RabbitMQ เป็นเซิร์ฟเวอร์ฐานข้อมูลหรือบางประเภท? ฉันจะบอกว่ามันเป็นมิดเดิลแวร์ที่เน้นข้อความพร้อมคุณสมบัติการคงอยู่เล็ก ๆ น้อย ๆ ที่ดีเพื่อไม่ให้ข้อความใด ๆ หายไป แต่ฉันจะไม่บันทึกข้อมูลด้วย แค่สองเซ็นต์ของฉัน
Osiriz

@Osiriz: คุณถูกต้อง ฉันอาจไม่ควรรวมไว้ในการสนทนานี้
CheddarMonkey

5

นี่คือฟังก์ชันที่จะบันทึก / อัปเดตคีย์ของอาร์เรย์ JSON ในคอลัมน์และฟังก์ชันอื่นที่ดึงค่า JSON ฟังก์ชั่นนี้จะถูกสร้างขึ้นสมมติว่าชื่อคอลัมน์ในการจัดเก็บอาร์เรย์ JSON เป็นJSON มันคือการใช้PDO

บันทึก / อัปเดตฟังก์ชัน

function save($uid, $key, $val){
 global $dbh; // The PDO object
 $sql = $dbh->prepare("SELECT `json` FROM users WHERE `id`=?");
 $sql->execute(array($uid));
 $data      = $sql->fetch();
 $arr       = json_decode($data['json'],true);
 $arr[$key] = $val; // Update the value
 $sql=$dbh->prepare("UPDATE `users` SET `json`=? WHERE `id`=?");
 $sql->execute(array(
   json_encode($arr), 
   $uid
 ));
}

ที่$ uidเป็น ID ของผู้ใช้$ คีย์ - คีย์ JSON เพื่อปรับปรุงและความคุ้มค่าของมันเป็นที่กล่าวถึงเป็น$ Val

รับฟังก์ชันมูลค่า

function get($uid, $key){
 global $dbh;
 $sql = $dbh->prepare("SELECT `json` FROM `users` WHERE `id`=?");
 $sql->execute(array($uid));
 $data = $sql->fetch();
 $arr  = json_decode($data['json'], true);
 return $arr[$key];
}

โดยที่$ keyเป็นคีย์ของอาร์เรย์JSONซึ่งเราต้องการค่า


1
สิ่งนี้ล้มเหลวในกรณีที่ขัดแย้งกันจะเกิดอะไรขึ้นถ้า json ที่คุณเพิ่งอ่านได้รับการอัปเดตโดยกระบวนการอื่นจากนั้นคุณบันทึก json ในเธรดปัจจุบันทับมัน? คุณอาจต้องล็อกเช่นSELECT FOR UPDATEหรือกำหนดเวอร์ชันภายในข้อมูล json
DhruvPathak

@DhruvPathak ได้โปรดปรับปรุงคำตอบโดยใช้SELECT FOR UPDATEเพื่อที่จะดียิ่งขึ้น ไม่รู้จะใช้ยังไง
Subin

3

การสนับสนุนต้นสำหรับการจัดเก็บ JSON ใน MySQL ได้รับการเพิ่มMySQL 5.7.7 JSON ห้องปฏิบัติการปล่อย ( ไบนารีลินุกซ์ , แหล่งที่มา )! ปล่อยดูเหมือนว่าจะมีการเติบโตจากชุดของฟังก์ชั่นที่ผู้ใช้กำหนด JSON-ที่เกี่ยวข้องทำให้ประชาชนกลับไปในปี 2013

การสนับสนุน JSON เนทีฟที่ตั้งขึ้นใหม่นี้ดูเหมือนจะมุ่งไปในทิศทางที่ดีมากรวมถึงการตรวจสอบความถูกต้องของ JSON บน INSERT ซึ่งเป็นรูปแบบการจัดเก็บไบนารีที่ได้รับการปรับให้เหมาะสมรวมถึงตารางการค้นหาในคำนำที่อนุญาตให้ฟังก์ชัน JSN_EXTRACT ทำการค้นหาแบบไบนารีแทนที่จะแยกวิเคราะห์ในทุกการเข้าถึง นอกจากนี้ยังมีฟังก์ชั่นใหม่ทั้งหมดสำหรับจัดการและสืบค้นประเภทข้อมูล JSON เฉพาะ:

CREATE TABLE users (id INT, preferences JSON);

INSERT INTO users VALUES (1, JSN_OBJECT('showSideBar', true, 'fontSize', 12));

SELECT JSN_EXTRACT(preferences, '$.showSideBar') from users;

+--------------------------------------------------+
| id   | JSN_EXTRACT(preferences, '$.showSideBar') |
+--------------------------------------------------+
| 1    | true                                      |
+--------------------------------------------------+

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

ในขณะที่มันยังคงเป็นวันแรกทีม MySQL เซิร์ฟเวอร์กำลังทำผลงานยอดเยี่ยมของการสื่อสารการเปลี่ยนแปลงใน บล็อก


2

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

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

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


2

JSON เป็นประเภทข้อมูลที่ถูกต้องในฐานข้อมูล PostgreSQL เช่นกัน อย่างไรก็ตามฐานข้อมูล MySQL ยังไม่รองรับ JSON อย่างเป็นทางการ แต่เป็นการอบ: http://mysqlserverteam.com/json-labs-release-native-json-data-type-and-binary-format/

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


1

ฉันใช้ json เพื่อบันทึกอะไรก็ได้สำหรับโปรเจ็กต์ฉันใช้สามตารางจริงๆ! หนึ่งสำหรับข้อมูลใน json หนึ่งสำหรับดัชนีของข้อมูลเมตาแต่ละรายการของโครงสร้าง json (แต่ละเมตาถูกเข้ารหัสโดย id ที่ไม่ซ้ำกัน) และอีกรายการสำหรับผู้ใช้เซสชันนั่นคือทั้งหมด เกณฑ์มาตรฐานนี้ไม่สามารถหาปริมาณได้ในสถานะเริ่มต้นของโค้ดนี้ แต่สำหรับตัวอย่างฉันคือมุมมองของผู้ใช้ (การรวมภายในกับดัชนี) เพื่อรับหมวดหมู่ (หรืออะไรก็ได้ในฐานะผู้ใช้ ... ) และมันช้ามาก (ช้ามาก มุมมองที่ใช้ใน mysql ไม่ใช่วิธีที่ดี) โมดูลการค้นหาในโครงสร้างนี้สามารถทำอะไรก็ได้ที่ฉันต้องการ แต่ฉันคิดว่า mongodb จะมีประสิทธิภาพมากกว่าในแนวคิดของการบันทึกข้อมูล json แบบเต็มนี้ สำหรับตัวอย่างของฉันฉันใช้มุมมองเพื่อสร้างต้นไม้ของหมวดหมู่และเบรดครัมบ์พระเจ้าของฉัน! มีคำถามมากมายให้ทำ! apache ไปเอง! และในความเป็นจริงสำหรับเว็บไซต์เล็ก ๆ นี้ฉันใช้ความรู้ php ที่สร้างต้นไม้และเบรดครัมบ์ การแยกข้อมูลทำได้โดยโมดูลการค้นหา (ซึ่งใช้ดัชนีเท่านั้น) ตารางข้อมูลจะใช้สำหรับการอัปเดตเท่านั้น ถ้าฉันต้องการฉันสามารถทำลายดัชนีทั้งหมดและสร้างใหม่ด้วยข้อมูลแต่ละรายการและทำงานย้อนกลับเช่นทำลายข้อมูลทั้งหมด (json) และสร้างใหม่ด้วยตารางดัชนีเท่านั้น โปรเจ็กต์ของฉันยังเด็กทำงานภายใต้ php และ mysql แต่บางครั้งฉันใช้ node js และ mongodb จะมีประสิทธิภาพมากกว่าสำหรับโปรเจ็กต์นี้

ใช้ json ถ้าคุณคิดว่าคุณทำได้แค่ทำเพราะคุณทำได้! และลืมมันไปหากมันเป็นความผิดพลาด พยายามเลือกทางเลือกที่ดีหรือไม่ดี แต่ลอง!

ต่ำ

ผู้ใช้ภาษาฝรั่งเศส


1
ไม่เข้าใจ. ฉันไม่ได้พูดภาษาอังกฤษโดยกำเนิด แต่ขอแนะนำให้คุณใช้จุด (.), ลูกน้ำ (,) และย่อหน้า (แป้น Enter) เพื่อจัดระเบียบความคิดของคุณ จากนั้นพยายามจัดระเบียบฐานข้อมูล
Diego Jancic

คุณพูดถูกคำตอบที่สับสนในความเป็นจริงต้องชัดเจนมากขึ้นโดยการแสดงตัวอย่าง แต่ถ้า mysql สามารถแทนที่ด้วย mongoDB ได้การใช้ json จะมีประสิทธิภาพมากขึ้น (เป็นแบบเนทีฟสำหรับ mongodb) หากจำเป็นต้องใช้ mysql ก็ลองอีกครั้งในอีกสองสามวัน!
ต่ำ

1

ฉันรู้ว่านี่มันสายไปแล้ว แต่ฉันก็มีสถานการณ์คล้าย ๆ กันที่ฉันใช้วิธีไฮบริดในการรักษามาตรฐาน RDBMS ของการปรับตารางให้เป็นมาตรฐานจนถึงจุดหนึ่งแล้วจัดเก็บข้อมูลใน JSON เป็นค่าข้อความเกินกว่าจุดนั้น ตัวอย่างเช่นฉันเก็บข้อมูลไว้ใน 4 ตารางตามกฎ RDBMS ของการทำให้เป็นมาตรฐาน อย่างไรก็ตามในตารางที่ 4 เพื่อรองรับสคีมาแบบไดนามิกฉันเก็บข้อมูลในรูปแบบ JSON ทุกครั้งที่ฉันต้องการดึงข้อมูลฉันจะดึงข้อมูล JSON แยกวิเคราะห์และแสดงใน Java สิ่งนี้ใช้ได้ผลสำหรับฉันจนถึงตอนนี้และเพื่อให้แน่ใจว่าฉันยังสามารถทำดัชนีเขตข้อมูลที่ฉันแปลงเป็นข้อมูล json ในตารางให้เป็นแบบมาตรฐานโดยใช้ ETL สิ่งนี้ช่วยให้มั่นใจได้ว่าในขณะที่ผู้ใช้ทำงานกับแอปพลิเคชันเขาต้องเผชิญกับความล่าช้าน้อยที่สุดและฟิลด์จะถูกเปลี่ยนเป็นรูปแบบที่เป็นมิตรกับ RDBMS สำหรับการวิเคราะห์ข้อมูลเป็นต้น


0

คุณสามารถใช้ส่วนสำคัญนี้: https://gist.github.com/AminaG/33d90cb99c26298c48f670b8ffac39c3

หลังจากติดตั้งลงในเซิร์ฟเวอร์ (เพียงต้องการสิทธิ์รูทไม่ใช่ขั้นสูง) คุณสามารถทำสิ่งนี้ได้:

select extract_json_value('{"a":["a","2"]}','(/a)')

มันจะกลับมา a 2 คุณสามารถส่งคืนอะไรก็ได้ใน JSON โดยใช้สิ่งนี้ส่วนที่ดีคือมันรองรับ MySQL 5.1,5.2,5.6 และคุณไม่จำเป็นต้องติดตั้งไบนารีใด ๆ บนเซิร์ฟเวอร์

อ้างอิงจากโครงการเก่าcommon-schemaแต่ปัจจุบันยังใช้งานได้ https://code.google.com/archive/p/common-schema/


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