Computer >> คอมพิวเตอร์ >  >> การเขียนโปรแกรม >> ฐานข้อมูล

คู่คี่:MongoDB และ MySQL

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

ในปัจจุบัน มีเหตุผลที่น่าสนใจในการผสมผสานและจับคู่ที่เก็บข้อมูล SQL ของคุณ (เช่น MySQL, PostgreSQL, Oracle หรือ SQLServer) กับที่เก็บข้อมูล NoSQL ของคุณ (MongoDB, CouchDB และ Neo4J เป็นต้น) แม้ว่า Oracle อาจยังคงเป็นระบบบันทึกที่ต้องการ สถานประกอบการ ไม่ใช่เกมเดียวในเมืองอีกต่อไป

นักพัฒนาเริ่มใช้ชุดค่าผสมของ SQL และ NoSQL เพื่อแก้ปัญหา ซึ่งบางครั้งขัดต่อความต้องการของ DBA หรือแผนกไอที

การเลือกเครื่องมือให้เหมาะสมกับงาน

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

Sadalage และ Fowler ทราบถึงความจำเป็นของการคงอยู่ของหลายภาษาใน NoSQL Distilled โดยกล่าวว่า:

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

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

ตัวเลือก Datastore แบ่งออกเป็นสองเกณฑ์:

  1. โครงสร้างของข้อมูลที่ถูกจัดเก็บ
  2. แบบสอบถามที่ใช้ในการโต้ตอบกับข้อมูล

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

ด้านล่างนี้ ฉันจะพูดถึงกรณีการใช้งานหนึ่งกรณี นั่นคือการเก็บถาวรข้อมูล CraigsList กับ MongoDB และคาดเดาว่าพวกเขาจะทำสิ่งนี้ให้สำเร็จได้อย่างไร

ผู้เล่น:MongoDB, MySQL และ CraigsList

MongoDB

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

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

ข้อมูลเพิ่มเติมเกี่ยวกับความแตกต่างของ MongoDB สามารถพบได้บนเว็บไซต์ของ MongoDB

MySQL

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

MySQL ช่วยให้เราใช้งานแบบจำลองข้อมูลเชิงสัมพันธ์แบบคลาสสิกได้ โดยใช้ทฤษฎีประเภทและทฤษฎีเซต มันถูกพัฒนาขึ้นในปี 1970 โดย E.F. Codd ความสามารถในการทำให้เป็นมาตรฐานทางโปรแกรม วางแผนหรือไตร่ตรองได้ ทำให้ระบบข้อมูลเชิงสัมพันธ์เป็นที่นิยมอย่างมาก อันที่จริง , ที่เก็บข้อมูลเหล่านี้ยังคงได้รับความนิยม เนื่องจากสามารถแก้ปัญหาการสร้างแบบจำลองข้อมูลในลักษณะทั่วไปได้

CraigsList

ธุรกิจออนไลน์ที่มีชื่อเสียงแห่งหนึ่งที่ใช้ทั้ง MongoDB และ MySQL datastore คือ CraigsList การใช้งานร่วมกันของที่เก็บข้อมูลทั้งสองมีระบุไว้ในกรณีศึกษาของ MongoDB แต่ด้านล่างนี้คือภาพร่างขนาดย่อ

เนื่องจากข้อกำหนดด้านกฎระเบียบ Craigslist จึงต้องเก็บรักษาบันทึกดิจิทัลของคลาสสิฟายด์ ด้วยจำนวนคลาสสิฟายด์ใหม่กว่าล้านรายการต่อวัน นั่นเป็นข้อมูลจำนวนมากสำหรับ CraigsList ที่จะเก็บรักษา มันใช้ที่เก็บข้อมูล MySQL เพื่อเก็บข้อมูลที่ใช้งานอยู่ทั้งหมดเกี่ยวกับคลาสสิฟายด์ ในขณะที่ MongoDB ใช้เพื่อจัดเก็บข้อมูลที่เก็บถาวร — อาจจะเป็นอะไรก็ได้ใน 30 วัน ในส่วนของการเปลี่ยนแปลงทางธุรกิจตามปกติ สคีมาข้อมูลของข้อมูลที่จัดเก็บจะเปลี่ยนแปลงไป ด้วยการใช้ MongoDB สำหรับข้อมูลที่เก็บไว้ CraigsList สามารถแบ่งกลุ่มข้อมูลอย่างมีประสิทธิภาพและลดปัญหาอันเนื่องมาจาก การโยกย้ายสคีมา

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

ทำอย่างไร

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

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

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

ตัวอย่างสคีมาสำหรับคลาสสิฟายด์จะมีลักษณะดังนี้ (นำมาใช้ใหม่อย่างไร้ยางอายจาก craigslist-clone):

CREATE TABLE `classifieds` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `title` varchar(75) COLLATE utf8_unicode_ci DEFAULT NULL,
  `description` text COLLATE utf8_unicode_ci,
  `location` varchar(75) COLLATE utf8_unicode_ci DEFAULT NULL,
  `adtype` varchar(1) COLLATE utf8_unicode_ci DEFAULT 'O',
  `email` varchar(75) COLLATE utf8_unicode_ci DEFAULT NULL,
  `phone` varchar(75) COLLATE utf8_unicode_ci DEFAULT NULL,
  `activation_code` varchar(40) COLLATE utf8_unicode_ci DEFAULT NULL,
  `status` tinyint(4) DEFAULT '0',
  `category_id` int(11) DEFAULT NULL,
  `subcategory_id` int(11) DEFAULT NULL,
  `city_id` int(11) DEFAULT NULL,
  `permalink` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
  `image_file_name` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
  `image_content_type` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
  `image_file_size` int(11) DEFAULT NULL,
  `created_at` datetime DEFAULT NULL,
  `updated_at` datetime DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

แน่นอน CraigsList มักจะมีสคีมาที่แตกต่างกัน และอย่างน้อยก็ค้นพบสคีมาปัจจุบันของพวกเขาหลังจากการทำซ้ำหลายครั้ง นอกจากนี้ พวกเขาอาจตัดสินใจเปลี่ยนวิธีการจัดระเบียบข้อมูลและเปลี่ยนสคีมาอีกครั้งในอนาคต เราต้องการใช้ created_at และ updated_at เพื่อตัดสินใจว่าเราจะจัดเก็บข้อมูลที่มีอยู่ใน MySQL เมื่อใด

สมมติว่านโยบายคลาสสิฟายด์ของ Craigslist ระบุว่าโฆษณาจะยังคงมีอยู่บนเว็บไซต์เป็นเวลาสองสัปดาห์ หลังจากเวลานี้ พวกเขาต้องการให้คลาสนั้นยังคงใช้งานได้ แต่ไม่จำเป็นต้องเปิดใช้งาน (ใน MySQL) เพื่อให้บรรลุเป้าหมายนี้ เราสามารถใช้ SQLAlchemy ร่วมกันได้ และ pymongo:

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

import sqlalchemy.schema

m = sqlalchemy.schema.MetaData("mysql://root:I'm required why?@192.0.2.3/craigslist")
m.reflect()

print m.tables.keys()

หากคุณเชื่อมต่อกับฐานข้อมูลได้สำเร็จ คุณจะเห็นคีย์ของคุณ (ชื่อคอลัมน์) พิมพ์ออกมาในรูปแบบหลามมาตรฐาน:[u'classifieds', u'cities', u'subcategories', u'categories'] เรายังคงต้องดึงข้อมูลแต่ละรายการออกจากตารางเหล่านี้ ไม่เพียงแต่เราจะดูได้เท่านั้น แต่ SQLAlchemy ยังมีอินเทอร์เฟซที่สวยงามเพื่อทำให้สิ่งนี้ง่ายขึ้นมาก

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

import sqlalchemy.sql

connection = m.bind.connect()

classifieds = m.tables['classifieds']

query = classifieds.select()

result = connection.execute(query)

for row in result:
    print dict(row.items())

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

ตัวอย่างต่อไปแสดงวิธีเชื่อมต่อและแทรกพจนานุกรมลงใน pymongo:

import pymongo

client = pymongo.MongoClient('mongodb://192.0.2.2')

db = client['craigslist']
collection = db['classifieds']
collection.insert({'_id': 1})

ปัญหาเดียวในตอนนี้คือวิธีที่ SQLAlchemy และ MongoDB ระบุ ID ของพวกเขา SQLAlchemy ใช้คีย์ของ id ในขณะที่ MongoDB ใช้คีย์ของ _id .ดังนั้นเราจึงต้องแปลคีย์นั้น (ขั้นตอนค่อนข้างง่าย):classified['_id'] = classified.pop('id') .

บทสรุป

แม้ว่าที่เก็บข้อมูล SQL และ NoSQL มักจะถูกมองว่าเป็นข้อเสนอทั้งหมดหรือไม่มีเลย แต่กลับกลายเป็นว่าสามารถใช้ร่วมกันเพื่อแก้ปัญหาที่ซับซ้อนได้ จากตัวอย่างนี้ เราพบว่าต้องใช้โค้ดเพียงเล็กน้อยสำหรับระบบที่ใช้ทั้ง MongoDB และ ที่เก็บข้อมูล MySQL อันที่จริงสิ่งนี้สามารถขับเคลื่อนโดย cron แทนที่จะถูก daemonized

ความยากในการใช้ datastore หลายๆ แห่งไม่ได้อยู่ที่การพัฒนาโค้ดการแปลหรือรหัสการโยกย้ายเสมอไป แต่การดูแลระบบเพิ่มเติมจะเพิ่มความยากขึ้น การดูแลรักษาที่เก็บข้อมูลหนึ่งแห่งนั้นต้องการผู้เชี่ยวชาญอยู่แล้ว (DBA หรือผู้ดูแลระบบที่มีความรู้เกี่ยวกับ datastore) และสิ่งนี้ ความต้องการความเชี่ยวชาญเพิ่มขึ้นเมื่อคุณแนะนำพื้นที่เก็บข้อมูลมากขึ้น

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

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