تخزين مرن للبيانات في MySQL (JSON)

يعمل ألكساندر روبن في Percona وقد أجرى في HighLoad ++ أكثر من مرة ، وهو مألوف لدى المشاركين كخبير في MySQL. من المنطقي أن نفترض أننا اليوم سوف نتحدث عن شيء متعلق MySQL. هذا صحيح ، لكن جزئيًا فقط ، لأننا سنتحدث أيضًا عن إنترنت الأشياء . ستكون القصة نصف مسلية ، خاصة الجزء الأول منها ، حيث ننظر إلى الجهاز الذي ابتكره ألكساندر لجني المشمش. هذه هي طبيعة المهندس الحقيقي - إذا كنت تريد الفاكهة ، فإنك تشتري رسومًا.



قبل التاريخ


بدأ كل شيء برغبة بسيطة في زراعة شجرة فواكه في منطقتها. قد يبدو الأمر بسيطًا جدًا - يمكنك الحضور إلى المتجر وشراء الشتلات. لكن في أمريكا ، السؤال الأول الذي يطرحه البائعون هو مقدار ضوء الشمس الذي ستتلقاه الشجرة. بالنسبة إلى ألكساندر ، اتضح أن هذا لغز غامض - من غير المعروف تمامًا كم أشعة الشمس في الموقع.

لمعرفة ذلك ، يمكن للطالب الخروج إلى الفناء كل يوم ، ومعرفة مقدار أشعة الشمس ، وكتابته في دفتر ملاحظات. ولكن هذا ليس هو الحال - من الضروري تجهيز كل شيء وأتمتة.


خلال العرض التقديمي ، تم تشغيل العديد من الأمثلة وتشغيلها على الهواء مباشرة. تريد صورة أكثر اكتمالا مما في النص ، والتحول إلى مشاهدة الفيديو.

لذلك ، من أجل عدم تسجيل ملاحظات الطقس في دفتر ملاحظات ، هناك عدد كبير من الأجهزة لأشياء الإنترنت - Raspberry Pi ، Raspberry Pi الجديدة ، Arduino - الآلاف من المنصات المختلفة. لكنني اخترت جهازًا يسمى الجسيمات الفوتون لهذا المشروع. إنه سهل الاستخدام للغاية ، ويكلف 19 دولارًا على الموقع الرسمي.

الشيء الجيد في الجسيمات فوتون هو:

  1. 100 ٪ حل سحابة.
  2. أي أجهزة استشعار مناسبة ، على سبيل المثال ، لاردوينو. كلهم تكلف أقل من دولار.

لقد صنعت هذا الجهاز ووضعته على العشب على الموقع. أنه يحتوي على سحابة جهاز الجسيمات ووحدة التحكم. يتصل هذا الجهاز عبر نقطة اتصال Wi-Fi ويرسل البيانات: الضوء ودرجة الحرارة والرطوبة. استمر الاختبار لمدة 24 ساعة على بطارية صغيرة ، وهو أمر جيد للغاية.

علاوة على ذلك ، لا أحتاج فقط إلى قياس الإضاءة وما إلى ذلك ونقلها إلى الهاتف (وهو أمر جيد حقًا - أستطيع أن أرى في الوقت الفعلي نوع الإضاءة لدي) ، ولكن أيضًا لتخزين البيانات . لهذا ، بطبيعة الحال ، كخبير محنك في MySQL ، اخترت MySQL.

كيف نكتب البيانات في MySQL


اخترت مخططًا معقدًا إلى حد ما:

  • أحصل على بيانات من وحدة التحكم في الجسيمات ؛
  • يمكنني استخدام Node.js لكتابتها إلى MySQL.

أنا أستخدم Particle JS API ، والتي يمكن تنزيلها من موقع Particle. أقوم بإنشاء اتصال مع MySQL وأكتب ، أي أقوم فقط بإدخال قيم INTO. هذا خط أنابيب.

وبالتالي ، يقع الجهاز في الفناء ، ويتصل عبر Wi-Fi بجهاز التوجيه المنزلي ويستخدم بروتوكول MQTT لنقل البيانات إلى الجسيمات. ثم المخطط: البرنامج على Node.js يعمل على الجهاز الظاهري ، الذي يستقبل البيانات من الجسيمات ويكتبها إلى MySQL.

بالنسبة للمبتدئين ، قمت ببناء الرسوم البيانية من البيانات الأولية في R. توضح الرسوم البيانية أن درجة الحرارة والإضاءة ترتفع أثناء النهار ، وتسقط ليلاً ، وترتفع الرطوبة - وهذا أمر طبيعي. ولكن هناك أيضًا ضوضاء على الرسم البياني ، وهو أمر نموذجي لأجهزة Internet of Things. على سبيل المثال ، عندما يزحف أحد الأخطاء إلى جهاز ويغلقه ، يمكن للمستشعر نقل بيانات غير ملائمة تمامًا. سيكون هذا مهمًا لمزيد من الدراسة.

الآن دعنا نتحدث عن MySQL و JSON ، والتي تغيرت في العمل مع JSON من MySQL 5.7 إلى MySQL 8. ثم سأعرض عرضًا تجريبيًا أستخدم MySQL 8 له (في وقت التقرير لم يكن هذا الإصدار جاهزًا للإنتاج بالفعل ، تم إصدار إصدار ثابت بالفعل).

الخلية تخزين البيانات


عندما نحاول تخزين البيانات المستلمة من أجهزة الاستشعار ، فكرنا الأول هو إنشاء جدول في MySQL :

CREATE TABLE 'sensor_wide' ( 'id' int (11) NOT NULL AUTO_INCREMENT, 'light' int (11) DEFAULT NULL, 'temp' double DEFAULT NULL, 'humidity' double DEFAULT NULL, PRIMARY KEY ('id') ) ENGINE=InnoDB 

يوجد هنا لكل مستشعر ولكل نوع بيانات عمود: الضوء ، درجة الحرارة ، الرطوبة.

هذا منطقي بما فيه الكفاية ، ولكن هناك مشكلة - ليست مرنة . لنفترض أننا نريد إضافة مستشعر آخر وقياس شيء آخر. على سبيل المثال ، يقوم بعض الأشخاص بقياس البيرة المتبقية في البرميل. ماذا تفعل في هذه الحالة؟

 alter table sensor_wide add water level double ...; 

كيفية الانحراف من أجل إضافة شيء إلى الجدول؟ تحتاج إلى عمل جدول بديل ، ولكن إذا قمت بإجراء جدول بديل في MySQL ، فأنت تعلم ما أتحدث عنه - هذا أمر صعب تمامًا. يعد تغيير الجدول في MySQL 8 و MariaDB أبسط بكثير ، ولكن هذه مشكلة كبيرة تاريخيا. لذلك إذا كنا بحاجة إلى إضافة عمود ، على سبيل المثال ، باسم البيرة ، فلن يكون الأمر بهذه البساطة.

مرة أخرى ، تظهر أجهزة الاستشعار ، تختفي ، ماذا يجب أن نفعل مع البيانات القديمة؟ على سبيل المثال ، نتوقف عن تلقي معلومات حول الإضاءة. أم أننا بصدد إنشاء عمود جديد - كيفية تخزين ما لم يكن هناك من قبل؟ النهج القياسي لاغٍ ، ولكن التحليل لن يكون مناسبًا للغاية للتحليل.

خيار آخر هو مخزن مفتاح / القيمة.

MySQL تخزين البيانات: مفتاح / قيمة


سيكون هذا أكثر مرونة : في المفتاح / القيمة سيكون هناك اسم ، على سبيل المثال ، درجة الحرارة ، وبالتالي ، البيانات.

 CREATE TABLE 'cloud_data' ( 'id' int (11) NOT NULL AUTO_INCREMENT, 'name' varchar(255) DEFAULT NULL, 'data' text DEFAULT NULL, 'updated_at' timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP PRIMARY KEY ('id') ) ENGINE=InnoDB 

في هذه الحالة ، تظهر مشكلة أخرى - لا توجد أنواع . لا نعرف ما نقوم بتخزينه في حقل "البيانات". يجب أن نعلنها كحقل نص. عندما أقوم بإنشاء جهاز إنترنت الأشياء الخاص بي ، أعرف نوع المستشعر الموجود ، وبالتالي النوع ، ولكن إذا كنت بحاجة إلى تخزين بيانات شخص آخر في نفس الجدول ، فلن أعرف البيانات التي يتم جمعها.

يمكنك تخزين العديد من الجداول ، ولكن إنشاء جدول جديد بالكامل لكل جهاز استشعار ليس جيدًا جدًا.

ما الذي يمكن عمله؟ - استخدم JSON.

MySQL تخزين البيانات: JSON


والخبر السار هو أنه في MySQL 5.7 ، يمكنك تخزين JSON كحقل.

 CREATE TABLE 'cloud_data_json' ( 'id' int (11) NOT NULL AUTO_INCREMENT, 'name' varchar(255) DEFAULT NULL, 'data' JSON, 'updated_at' timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP PRIMARY KEY ('id') ) ENGINE=InnoDB; 

قبل ظهور MySQL 5.7 ، قام الناس أيضًا بتخزين JSON ، ولكن كحقل نصي. يتيح لك الحقل JSON في MySQL تخزين JSON نفسه بكفاءة أكبر. بالإضافة إلى ذلك ، بناءً على JSON ، يمكنك إنشاء أعمدة وفهارس افتراضية بناءً عليها.

المشكلة الطفيفة الوحيدة هي أن الجدول سوف ينمو في الحجم أثناء التخزين . ولكن بعد ذلك نحصل على الكثير من المرونة.

يعد حقل JSON أفضل لتخزين JSON من حقل النص لأنه:

  • يوفر التحقق التلقائي من المستند . أي إذا حاولنا كتابة شيء غير صالح هناك ، فسيحدث خطأ.
  • هذا هو تنسيق التخزين الأمثل . يتم تخزين JSON في تنسيق ثنائي ، مما يسمح لك بالتبديل من وثيقة JSON إلى أخرى - ما يسمى تخطي.

لتخزين البيانات في JSON ، يمكننا ببساطة استخدام SQL: إنشاء INSERT ، ووضع "البيانات" هناك والحصول على البيانات من الجهاز.

 … stream.on('event', function(data) { var query = connection.query( 'INSERT INTO cloud_data_json (client_name, data) VALUES (?, ?)', ['particle', JSON.stringify(data)] ) … (demo) 

عرض


للتدليل ( هنا بدايته في الفيديو) ، يستخدم المثال جهازًا افتراضيًا به SQL.



أدناه جزء من البرنامج.



أقوم INSERT INTO cloud_data (name, data) ، يمكنني الحصول على البيانات بالفعل بتنسيق JSON ، ويمكنني أن INSERT INTO cloud_data (name, data) مباشرة إلى MySQL كما هي ، دون التفكير في ما هو بداخلها.

كما اتضح فيما بعد ، باستخدام هذه السحابة ، يمكنك الوصول ليس فقط إلى بيانات جهازي ، ولكن عمومًا كل البيانات التي تستخدمها هذه الجسيمات. يبدو أن العمل حتى الآن. يرسل الأشخاص الذين يستخدمون Particle Photon في جميع أنحاء العالم بعض البيانات: الباب مفتوحًا أمام المرآب ، أو ما تبقى من الجعة كذا وكذا ، أو أي شيء آخر. لا يُعرف مكان وجود هذه الأجهزة ، ولكن يمكن الحصول على هذه البيانات. الفرق الوحيد هو أنه عندما أحصل على بياناتي ، أكتب شيئًا مثل: deviceId: 'mine' .

عندما نقوم بتشغيل الشفرة ، نحصل على دفق من بعض البيانات من أجهزة شخص آخر تقوم بعمل ما.



لا نعرف مطلقًا ما هي هذه البيانات: TTL ، المنشور_التالي ، الجوهر ، حالة الباب (الباب مفتوح) ، الترحيل.

هذا مثال رائع. افترض أنني أحاول وضع هذا في MySQL في بنية بيانات عادية. يجب أن أعرف ما هو الباب ، ولماذا يفتح ، وما هي المعايير العامة التي يمكن أن يستغرقها. إذا كان لديّ JSON ، فأكتبه مباشرةً على MySQL كحقل JSON.



من فضلك ، لقد تم تسجيل كل شيء.



مخزن الوثائق


يعد مخزن المستندات محاولة في MySQL لتوفير مساحة تخزين لـ JSON. أنا حقاً أحب SQL ، وأنا على دراية بها ، يمكنني تقديم أي استعلام SQL ، إلخ. لكن الكثيرين لا يحبون SQL لأسباب متعددة ، ويمكن أن يكون متجر المستندات حلاً لهم ، لأنه يمكنك من خلاله الاستخراج من SQL والاتصال بـ MySQL وكتابة JSON مباشرةً هناك.


هناك احتمال آخر ظهر في MySQL 5.7: استخدام بروتوكول مختلف ، ومنفذ مختلف ، وهناك حاجة أيضًا إلى برنامج تشغيل آخر. بالنسبة إلى Node.js (في الواقع ، لأي لغة برمجة - PHP أو Java أو ما إلى ذلك) ، فإننا نتصل بـ MySQL باستخدام بروتوكول مختلف ويمكننا نقل البيانات بتنسيق JSON. مرة أخرى ، لا أعرف ما لدي في هذا JSON - معلومات حول الأبواب أو أي شيء آخر ، أنا فقط أتخلص من البيانات في MySQL ، ثم سنكتشفها.

 const mysqlx = require('@mysql/xdevapi*); // MySQL Connection var mySession = mysqlx.gctSession({ host: 'localhost', port: 33060, dbUser: 'photon* }); … session.getSchema("particle").getCollection("cloud_data_docstore") .add( data ) .execute(function (row) { }).catch(err => { console.log(err); }) .then( -Function (notices) { console.log("Wrote to MySQL") }); ...https://dev.mysql.com/doc/dev/connector-nodejs/ 

إذا كنت ترغب في تجربة هذا ، فيمكنك تكوين MySQL 5.7 بحيث يفهم ويسمع على المنفذ المناسب Document Store أو X DevAPI. اعتدت موصل nodejs.

هذا مثال على ما أكتب هناك: البيرة ، وما إلى ذلك. بالتأكيد لا أعرف ما الذي يوجد. نحن الآن نكتبها ونحللها لاحقًا.



النقطة التالية من برنامجنا هي كيفية معرفة ما هناك؟

تخزين بيانات MySQL: فهارس JSON +


هناك ميزة رائعة في JSON و MySQL 5.7 يمكنها سحب الحقول من JSON. هذا هو السكر النحوي في وظيفة JSON_EXTRACT. أعتقد أن هذا مريح للغاية.

البيانات الموجودة في حالتنا هي اسم العمود الذي تم تخزين JSON فيه ، والاسم هو حقلنا. الاسم والبيانات المنشورة - هذا هو كل ما يمكننا سحبه بهذه الطريقة.

 select data->>'$.name' as data_name, data->>'$.data' as data, data->>'$.published_at' as published from cloud_data_json order by data->'$.published_at' desc limit 10; 

في هذا المثال ، أريد أن أرى ما كتبته في جدول MySQL ، والسجلات العشر الأخيرة. أقوم بتقديم هذا الطلب وأحاول تنفيذه. لسوء الحظ ، هذا سوف يعمل لفترة طويلة جدا .

بطريقة منطقية ، لن تستخدم MySQL أي فهارس في هذه الحالة. نقوم بسحب البيانات من JSON ونحاول تطبيق نوع من المرشحات والفرز. في هذه الحالة ، نحصل على استخدام filesort.

 EXPLAIN select data->>'$.name' as data_name ... order by data->>'$.published_at' desc limit 10 select_type: SIMPLE table: cloud_data_json possible_keys: NULL key: NULLrows: 101589 filtered: 100.00 Extra: Using filesort 

استخدام filesort هو سيء للغاية ، بل هو نوع خارجي.

والخبر السار هو أنه يمكنك اتخاذ خطوتين لتسريع ذلك.

الخطوة 1. إنشاء عمود الظاهري


 mysql> ALTER TABLE cloud_data_json -> ADD published_at DATETIME(6) -> GENERATED ALWAYS AS (STR_TO_DATE(data->>'$.published_at',"%Y-%m-%dT%T.%fZ")) VIRTUAL; Query OK, 0 rows affected (0.01 sec) Records: 0 Duplicates: 0 Warnings: 0 

أقوم بإجراء EXTRACT ، أي سحب البيانات من JSON وبناءً عليها أقوم بإنشاء عمود افتراضي. لا يتم تخزين العمود الظاهري في MySQL 5.7 وفي MySQL 8 - إنه فقط القدرة على إنشاء عمود منفصل.

أنت تسأل كيف هو ، قلت أن ALTER TABLE هو مثل هذه العملية الطويلة. لكن هنا ليس سيئًا للغاية. إنشاء عمود افتراضي سريع . هناك نقص ، ولكن في الواقع ، يوجد في MySQL قفل لجميع عمليات DDL. ALTER TABLE هي عملية سريعة إلى حد ما ، ولا تقوم بإعادة إنشاء الجدول بأكمله.

لقد أنشأنا عمودًا افتراضيًا هنا. اضطررت إلى تحويل التاريخ ، لأنه في JSON يتم تخزينه بتنسيق ISO ، ولكن هنا يستخدم MySQL تنسيقًا مختلفًا تمامًا. لإنشاء عمود ، قمت بتسميته ، وأعطته نوعًا وقلت أنني سأقوم بالتسجيل هناك.

لتحسين الاستعلام الأصلي ، تحتاج إلى سحب المنشور والاسم. منشور منشور بالفعل ، الاسم أسهل - فقط قم بعمل عمود افتراضي.

 mysql> ALTER TABLE cloud_data_json -> ADD data_name VARCHAR(255) -> GENERATED ALWAYS AS (data->>'$.name') VIRTUAL; Query OK, 0 rows affected (0.01 sec) Records: 0 Duplicates: 0 Warnings: 0 

الخطوة 2. إنشاء فهرس


في الكود أدناه ، أقوم بإنشاء فهرس على المنشور _at وتنفيذ الاستعلام:

 mysql> alter table cloud_data_json add key (published_at); Query OK, 0 rows affected (0.31 sec) Records: 0 Duplicates: 0 Warnings: 0 mysql> explain select data_name, published_at, data->>'$.data' as data from cloud_data_json order by published_at desc limit 10\G table: cloud_data_json type: index possible_keys: NULL key: published_at key_len: 9 rows: 10 filtered: 100.00 Extra: Backward index scan 

يمكنك أن ترى أن MySQL يستخدم الفهرس بالفعل. هذا هو الأمثل من قبل النظام. في هذا المثال ، لا يتم فهرسة البيانات والاسم. يستخدم MySQL الترتيب حسب البيانات ، ولأن لدينا فهرسًا على المنشور_at ، فإنه يستخدمه.

علاوة على ذلك ، يمكنني استخدام نفس السكر في بناء الجملة STR_TO_DATE(data->>'$.published_at',"%Y-%m-%dT%T.%fZ") بدلاً من المنشور STR_TO_DATE(data->>'$.published_at',"%Y-%m-%dT%T.%fZ") ترتيب بالترتيب. لا يزال MySQL يفهم أن هناك فهرس في هذا العمود والبدء في استخدامه.

هناك بالفعل مشكلة صغيرة مع هذا. لنفترض أنني أريد فرز البيانات ليس فقط حسب المنشور ، ولكن أيضًا بالاسم.

 mysql> explain select data_name, published_at, data->>'$.data' as data from cloud_data_json order by published_at desc, data_name asc limit 10\G select_type: SIMPLE table: cloud_data_json partitions: NULL type: ALL possible_keys: NULL key: NULL key_len: NULL ref: NULL rows: 101589 filtered: 100.00 Extra: Using filesort 

إذا كان جهازك يعالج عشرات الآلاف من الأحداث في الثانية الواحدة ، فلن يقدم المنشور_at نوعًا جيدًا ، حيث ستكون هناك تكرارات. لذلك ، نضيف فرزًا آخر حسب اسم_البيانات. هذا استعلام نموذجي ليس فقط لإنترنت الأشياء: أعطني الأحداث العشر الأخيرة ، ولكن رتبها حسب التاريخ ، ثم ، على سبيل المثال ، حسب الاسم الأخير للشخص بترتيب تصاعدي. للقيام بذلك ، في المثال أعلاه ، يوجد حقلان ويتم تحديد مفتاحي فرز: تنازلي وتصاعدي.

بادئ ذي بدء ، في هذه الحالة ، لن يستخدم MySQL الفهارس. في هذه الحالة بالذات ، يقرر MySQL أن الفحص الكامل للجدول سيكون أكثر ربحية من استخدام الفهرس ، ومرة ​​أخرى يتم استخدام عملية الملفات البطيئة للغاية.

الجديد في MySQL 8.0


تنازلي / تصاعدي


في MySQL 5.7 ، لا يمكن تحسين مثل هذا الاستعلام ، إلا إذا كان ذلك على حساب أشياء أخرى. في MySQL 8 ، كانت هناك فرصة حقيقية لتحديد الفرز لكل حقل.

 mysql> alter table cloud_data_json add key published_at_data_name (published_at desc, data_name asc); Query OK, 0 rows affected (0.44 sec) Records: 0 Duplicates: 0 Warnings: 0 

الشيء الأكثر إثارة للاهتمام هو أن المفتاح التنازلي / التصاعدي بعد اسم الفهرس منذ فترة طويلة في SQL. حتى في الإصدار الأول من MySQL 3.23 ، يمكنك تحديد المنشور تنازليًا أو المنشور تصاعديًا. تقبل MySQL هذا ، لكنها لم تفعل شيئًا ، أي أنه يتم فرزه دائمًا في اتجاه واحد.

في MySQL 8 ، تم إصلاح هذا والآن هناك مثل هذه الميزة. يمكنك إنشاء حقل بترتيب تنازلي مع فرز افتراضي.

دعنا نعود ثانية وننظر إلى المثال من الخطوة 2 مرة أخرى.

لماذا يعمل ، وإلا فإنه لا؟ يعمل هذا لأنه في فهارس MySQL عبارة عن شجرة B ، ويمكن قراءة فهارس B-tree من البداية ومن النهاية. في هذه الحالة ، يقرأ MySQL الفهرس من النهاية وكل شيء على ما يرام. لكن إذا فعلنا تنازليًا وصعوديًا ، فلن تتمكن من القراءة. يمكنك القراءة بنفس الترتيب ، لكن لا يمكنك الجمع بين نوعين - تحتاج إلى إعادة الترتيب.

نظرًا لأننا نقوم بتحسين حالة محددة للغاية ، يمكننا إنشاء فهرس لها وتحديد نوع معين: هنا publish_at تنازلي ، data_name تصاعدي. يستخدم MySQL هذا الفهرس ، وسيكون كل شيء جيدًا وسريعًا.

 mysql> explain select data_name, published_at, data->>'$.data' as data from cloud_data_json order by published_at desc limit 10\G select_type: SIMPLE table: cloud_data_json partitions: NULL type: index possible_keys: NULL key: published_at_data_name key_len: 267 ref: NULL rows: 10 filtered: 100.00 Extra: NULL 

هذه هي سمة من سمات MySQL 8 ، والتي أصبحت الآن ، وقت النشر ، متاحة بالفعل وجاهزة للاستخدام في الإنتاج.

نتائج الانتاج


هناك شيئان أكثر إثارة للاهتمام أرغب في عرضهما:

1. طباعة جميلة ، وهذا هو ، إخراج جميل من البيانات إلى الشاشة. باستخدام SELECT العادي ، لن يتم تنسيق JSON.

 mysql> select json_pretty(data) from cloud_data_json where data->>'$.data' like '%beer%' limit 1\G … json_pretty(data): { "ttl": 60, "data": "FvGav,tagkey=beer-store spFridge=7.00,pvFridge=7.44", "name": "LOG_DATA_DEBUG", "coreid": "3600....", "published_at": "2017-09-28T18:21:16.517Z" } 

2. يمكننا القول أن MySQL ستنتج النتيجة في شكل صفيف JSON أو كائن JSON ، وحدد الحقول ، ومن ثم سيتم تنسيق الإخراج كـ JSON.

البحث عن النص الكامل داخل مستندات JSON


إذا كنا نستخدم نظام تخزين مرنًا ولا نعرف ماذا يوجد داخل JSON ، فسيكون من المنطقي استخدام البحث عن النص الكامل.

لسوء الحظ ، البحث عن النص الكامل له حدوده . أول ما جربته هو فقط إنشاء مفتاح النص الكامل. حاولت أن أفعل هذا الشيء:

 mysql> alter table cloud_data_json_indexes add fulltext key (data); ERROR 3152 (42000): JSON column 'data' supports indexing only via generated columns on a specified ISON path. 

لسوء الحظ هذا لا يعمل. حتى في MySQL 8 ، فإن إنشاء فهرس نص كامل ببساطة عن طريق حقل JSON أمر مستحيل للأسف. بالطبع ، أود الحصول على هذه الوظيفة - ستكون القدرة على البحث على الأقل عن طريق مفاتيح JSON مفيدة للغاية.

ولكن إذا لم يكن ذلك ممكنًا بعد ، فلنقم بإنشاء عمود افتراضي. في حالتنا ، يوجد حقل بيانات ، وسيكون من المثير للاهتمام أن نرى ما بداخلنا.

 mysql> ALTER TABLE cloud_data_json_indexes -> ADD data_data VARCHAR(255) -> GENERATED ALWAYS AS (data->>'$.data') VIRTUAL; Query OK, 0 rows affected (0.01 sec) Records: 0 Duplicates: 0 Warnings: 0 mysql> alter table cloud_data_json_indexes add fulltext key ft_json(data_name, data_data); ERROR 3106 (HY000): 'Fulltext index on virtual generated column' is not supported for generated columns. 

لسوء الحظ ، هذا لا يعمل أيضًا - لا يمكنك إنشاء فهرس نص كامل في عمود افتراضي .

إذا كان الأمر كذلك ، فلنقم بإنشاء عمود مخزن. يسمح لك MySQL 5.7 بإعلان عمود كحقل مخزن.
 mysql> ALTER TABLE cloud_data_json_indexes -> ADD data_name VARCHAR(255) CHARACTER SET UTF8MB4 -> GENERATED ALWAYS AS (data->>'$.name') STORED; Query OK, 123518 rows affected (1.75 sec) Records: 123518 Duplicates: 0 Warnings: 0 mysql> alter table cloud_data_json_indexes add fulltext key ft_json(data_name); Query OK, 0 rows affected, 1 warning (3.78 sec) Records: 0 Duplicates: 0 Warnings: 1 mysql> show warnings; +------------+--------+---------------------------------------------------+ | Level | Code | Message | +------------+--------+---------------------------------------------------+ | Warning | 124 | InnoDB rebuilding table to add column FTS_DOC_ID | +------------+--------+---------------------------------------------------+ 

في الأمثلة السابقة ، أنشأنا أعمدة افتراضية غير مخزنة ، لكن الفهارس يتم إنشاؤها وتخزينها. في هذه الحالة ، كان علي أن أخبر MySQL أن هذا هو عمود STORED ، أي أنه سيتم إنشاؤه وسيتم نسخ البيانات إليه. بعد ذلك ، أنشأ MySQL فهرس نص كامل ، لهذا كان علينا إعادة إنشاء الجدول. ولكن هذا القيد هو في الواقع بحث InnoDB و InnoDB عن النص الكامل: يجب عليك إعادة إنشاء الجدول لإضافة معرف بحث عن النص الكامل.

ومن المثير للاهتمام ، في MySQL 8 ، كان هناك تشفير UTF8 MB4 جديد للرموز . بالطبع ، ليس تمامًا بالنسبة لهم ، ولكن لأنه في UTF8MB3 هناك بعض المشكلات في اللغات الروسية والصينية واليابانية وغيرها.

 mysql> ALTER TABLE cloud_data_json_indexes -> ADD data_data TEXT CHARACTER SET UTF8MB4 -> GENERATED ALWAYS AS ( CONVERT(data->>'$.data' USING UTF8MB4) ) STORED Query OK, 123518 rows affected (3.14 sec) Records: 123518 Duplicates: 0 Warnings: 0 

وفقًا لذلك ، يجب على MySQL 8 تخزين بيانات JSON في UTF8MB4. ولكن سواء كان ذلك بسبب حقيقة أن Node.js يتصل بـ Device Cloud ، وأن هناك شيئًا ما مكتوبًا هناك بشكل غير صحيح ، أو أنه خطأ في الإصدار التجريبي ، لم يحدث هذا. لذلك ، كان عليّ تحويل البيانات قبل كتابتها إلى عمود مخزن.

 mysql> ALTER TABLE cloud_data_json_indexes DROP KEY ft_json, ADD FULLTEXT KEY ft_json(data_name, data_data); Query OK, 0 rows affected (1.85 sec) Records: 0 Duplicates: 0 Warnings: 0 

بعد ذلك ، تمكنت من إنشاء بحث كامل النص في حقلين: على اسم JSON وعلى بيانات JSON.

ليس فقط إنترنت الأشياء


JSON ليس فقط إنترنت الأشياء. يمكن استخدامه لأشياء أخرى مثيرة للاهتمام:

  • الحقول المخصصة (CMS) ؛
  • الهياكل المعقدة ، إلخ ؛

يمكن تنفيذ بعض الأشياء بسهولة أكبر باستخدام نظام تخزين بيانات مرن. تم تقديم مثال ممتاز في Oracle OpenWorld: حجوزات السينما. من الصعب جدًا تنفيذ ذلك في النموذج العلائقي - تحصل على العديد من الجداول التابعة ، الصلات ، إلخ. من ناحية أخرى ، يمكننا تخزين الغرفة بأكملها كهيكل JSON ، على التوالي ، كتابتها إلى MySQL في جداول أخرى واستخدامها بالطريقة المعتادة: إنشاء فهارس على أساس JSON ، إلخ. يتم تخزين الهياكل المعقدة بشكل مريح في تنسيق JSON.



هذه هي الشجرة التي تم زرعها بنجاح. لسوء الحظ ، بعد بضع سنوات ، أكلت الغزلان ، لكن هذه قصة مختلفة تمامًا.

هذا التقرير هو مثال ممتاز على كيفية نمو قسم كامل من موضوع واحد في مؤتمر كبير ، ثم حدث منفصل منفصل. في حالة إنترنت الأشياء ، حصلنا على InoThings ++ - مؤتمر للمهنيين في سوق إنترنت الأشياء ، والذي سيعقد للمرة الثانية في 4 أبريل.

يبدو أن الحدث الرئيسي للمؤتمر هو اجتماع المائدة المستديرة "هل نحن بحاجة إلى معايير وطنية على إنترنت الأشياء؟" ، والتي ستُستكمل عضويا بتقارير تطبيقية شاملة. تعرف على ما إذا كانت الأنظمة المحملة بكثافة تتحرك بشكل صحيح إلى IIoT.

Source: https://habr.com/ru/post/ar443422/


All Articles