Тъй като повечето, ако не и цялата 2018 г. зад нас (в зависимост от това кога четете тази публикация), няма съмнение, че това беше фантастична година за SQL бази данни с отворен код.
PostgreSQL 11 и MySQL 8 бяха пуснати, предоставяйки на двете общности много за „разговор '. Честно казано, и двамата доставчици са въвели много значителни промени и допълнения в съответните си издания и заслужават тяхната похвала и признания.
Обикновено гостувам на публикация за първото тук в блога на Severalnines (Много благодаря на страхотна организация!), но също имам интерес към второто. С много публикации в блога на моя собствен уебсайт (връзка в моя раздел с биография), насочени предимно към MySQL версия 5.7, той (MySQL) винаги е в периферните ми устройства.
И така, какво има MySQL 8, което версията 5.7 няма? Какви са подобренията? Е, има много. Всъщност твърде много, за да бъдат обхванати само в една публикация в блога.
Наскоро надстроих до версия 8 в настоящата си среда за обучение/разработване на Linux, така че реших да опитам да посоча някои от тях.
Не мога да ви гарантирам задълбочена дискусия относно вашия „любим ' нови функции). От друга страна, ще посетя онези, които са привлекли вниманието ми или чрез личен интерес, или чрез многото страхотни публикации в блога, публикувани през годината във версия 8.
MySQL става все по-добър и по-добър... Страхотни подобрения във версия 8!
Роли
С ролите DBA могат да смекчат излишъка, когато много потребители споделят една и съща привилегия или набор от привилегии.
Ролите са част от стандарта SQL.
След като създадете конкретна роля с желаните/изискваните привилегии, можете да присвоите на потребителите тази конкретна роля чрез командата GRANT или по подобен начин „отнема ' с REVOKE.
Ролите идват с многобройни предимства и за да улесните живота малко, има няколко таблици, които да ви помогнат да ги следите:
-
mysql.role_edges - Тук намирате тези роли и потребителите, които са им назначени.
mysql> DESC mysql.role_edges; +-------------------+---------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +-------------------+---------------+------+-----+---------+-------+ | FROM_HOST | char(60) | NO | PRI | | | | FROM_USER | char(32) | NO | PRI | | | | TO_HOST | char(60) | NO | PRI | | | | TO_USER | char(32) | NO | PRI | | | | WITH_ADMIN_OPTION | enum('N','Y') | NO | | N | | +-------------------+---------------+------+-----+---------+-------+ 5 rows in set (0.01 sec)
-
mysql.default_roles – Съхранява всички роли по подразбиране и присвоените потребители.
mysql> DESC mysql.default_roles; +-------------------+----------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +-------------------+----------+------+-----+---------+-------+ | HOST | char(60) | NO | PRI | | | | USER | char(32) | NO | PRI | | | | DEFAULT_ROLE_HOST | char(60) | NO | PRI | % | | | DEFAULT_ROLE_USER | char(32) | NO | PRI | | | +-------------------+----------+------+-----+---------+-------+ 4 rows in set (0.00 sec)
Комбинацията от двете таблици (не в смисъла на SQL JOIN) по същество осигурява „централизирано местоположение ' където можете:да познавате, наблюдавате и оценявате всички ваши внедрени привилегии и присвоения на потребителска роля.
Вероятно най-простият примерен сценарий за използване на роли би бил:
Имате няколко потребители, които се нуждаят от „достъп само за четене ' на конкретна таблица, следователно, изискваща поне привилегията SELECT. Вместо да го предоставяте (SELECT) поотделно на всеки потребител, можете да установите (създадете) роля с тази привилегия, след което да присвоите тази роля на тези потребители.
Но ролите идват с малка „уловка '. Веднъж създаден и присвоен на потребител, получаващият потребител трябва да има активна зададена роля по подразбиране по време на удостоверяване при влизане.
Докато става въпрос за роли и потребители, смятам, че е важно да спомена промяната, внедрена в MySQL 8 по отношение на компонента validate_password, който е вариант на плъгина validate_password, използван във версия 5.7.
Този компонент предоставя различни отделни „категории ' на проверка на паролата:ниска, средна (по подразбиране) и силна. Посетете документацията на компонента validate_password за пълен преглед на спецификата за валидиране на всяко ниво.
NoSQL се смесва със SQL – Магазинът за документи
Тази функция все още научавам, въпреки мимолетния интерес към MongoDB в началото на 2016 г. Към днешна дата интересът, изучаването и ученето ми бяха фокусирани единствено върху „SQL“. Въпреки това съм наясно (чрез много четене в мрежата), че мнозина са развълнувани от този тип структуриране (ориентирано към документи), преплетено с „релационен SQL“, който вече е наличен в хранилището за документи на MySQL 8.
По-долу са изброени много предимства, налични при използване на хранилището за документи. Уверете се и споменете вашите любими, които може да съм пропуснал в секцията за коментари:
- Типът данни JSON се поддържа от MySQL версия 5.7.8, но версия 8 въведе значителни подобрения за работа с JSON. Нови функции, специфични за JSON, заедно със „стенография ' оператори, които могат да се използват вместо множество извиквания на функции - с еднакви резултати/изход.
- Може би едно от най-важните предимства е, че вече няма нужда да внедрявате и работите с множество решения за бази данни, тъй като NoSQL, SQL или комбинация от двете се поддържат в хранилището за документи.
- „DevAPI“ предоставя безпроблемни възможности за работен поток в контекста на NoSQL данни (колекции и документи). (Посетете официалното ръководство за потребителя на DevAPI за повече информация).
- Мощни сесии на команден ред, използващи Python, SQL или Javascript като език на „обвивка“.
- Съвместим с ACID.
- Бързо изследвайте и откривайте данните си, без да дефинирате схема, както бихте направили в релационен модел.
Общи таблични изрази (CTE или клаузата WITH)
Какво друго можете да кажете за CTE? Тези неща променят играта! Като за начало, какво точно е общ израз на таблица?
От Уикипедия:
„Общ табличен израз или CTE (в SQL) е временен набор от резултати, извлечен от проста заявка и дефиниран в рамките на обхвата на изпълнение на оператор SELECT, INSERT, UPDATE или DELETE.
Ще дам прост пример, демонстриращ CTE. Пълната им мощ обаче не е впрегната в този раздел, тъй като има много по-сложни примери за използване от тези.
Имам проста таблица с имена с това описание и данни:
mysql> DESC name;
+--------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+--------+-------------+------+-----+---------+-------+
| f_name | varchar(20) | YES | | NULL | |
| l_name | varchar(20) | YES | | NULL | |
+--------+-------------+------+-----+---------+-------+
2 rows in set (0.00 sec)
mysql> SELECT * FROM name;
+--------+------------+
| f_name | l_name |
+--------+------------+
| Jim | Dandy |
| Johhny | Applesauce |
| Ashley | Zerro |
| Ashton | Zerra |
| Ashmon | Zerro |
+--------+------------+
5 rows in set (0.00 sec)
Нека разберем колко фамилни имена започват с „Z“:
mysql> SELECT *
-> FROM name
-> WHERE l_name LIKE 'Z%';
+--------+--------+
| f_name | l_name |
+--------+--------+
| Ashley | Zerro |
| Ashton | Zerra |
| Ashmon | Zerro |
+--------+--------+
3 rows in set (0.00 sec)
Достатъчно лесно.
Въпреки това, като използвате клаузата WITH, можете да „достъп ' същия набор от резултати от заявка (който може да се разглежда като извлечена таблица) и се позовава на него по-късно в рамките на същия израз - или 'обхват ':
WITH last_Z AS (
SELECT *
FROM name
WHERE l_name LIKE 'Z%')
SELECT * FROM last_Z;
+--------+--------+
| f_name | l_name |
+--------+--------+
| Ashley | Zerro |
| Ashton | Zerra |
| Ashmon | Zerro |
+--------+--------+
3 rows in set (0.00 sec)
По принцип присвоявам име на заявката, увивайки го в скоби. След това просто изберете данните, които искам от това, което сега е last_Z CTE.
Last_Z CTE предоставя пълен набор от резултати, така че можете да го филтрирате още повече в рамките на същия израз:
WITH last_Z AS (
SELECT *
FROM name
WHERE l_name LIKE 'Z%')
SELECT f_name, l_name FROM last_Z WHERE l_name LIKE '%a';
+--------+--------+
| f_name | l_name |
+--------+--------+
| Ashton | Zerra |
+--------+--------+
1 row in set (0.00 sec)
Няколко от по-мощните функции са „верижно ' множество CTE заедно и препратка към други CTE в CTE.
Ето един пример, който да ви даде идея (макар и не толкова полезен):
WITH last_Z AS (
SELECT *
FROM name
WHERE l_name LIKE 'Z%'),
best_friend AS (
SELECT f_name, l_name
FROM last_Z
WHERE l_name LIKE '%a')
SELECT * from best_friend;
+--------+--------+
| f_name | l_name |
+--------+--------+
| Ashton | Zerra |
+--------+--------+
1 row in set (0.00 sec)
В горната заявка можете да видите къде отделих last_Z CTE от best_friend CTE със запетая, след което увих тази заявка в скоби след ключовата дума AS.
Забележете, че тогава мога да се позова на (и да използвам) last_Z CTE, за да дефинирам по същество CTE на най-добрия_приятел.
Ето няколко причини, поради които CTE са толкова значително подобрение във версия 8:
- Други доставчици на SQL поддържат CTE (много от по-ранните версии в рамките на тяхната индивидуална екосистема) и сега MySQL 8 запълни празнината в тази област.
- Стандартно включване на SQL.
- В някои случаи (където е уместно) CTE са по-добър вариант от временни таблици, изгледи, извлечени таблици (или вградени изгледи) и някои подзаявки.
- CTE могат да осигурят „в движение ' набор от резултати от изчисления, към който можете да правите запитвания.
- Един CTE може да се позовава на себе си – известен като рекурсивен CTE (не е демонстриран тук).
- CTE могат да назовават и използват други CTE
Функции на прозореца
Аналитичните заявки вече са възможни в MySQL 8. Тъй като функциите на прозореца не са моята силна страна, аз съм фокусиран върху по-задълбочено проучване и по-добро разбиране за тях като цяло, продължавайки напред. Следващите примери са предимно елементарни според моето разбиране. Предложения, съвети и най-добри практики са добре дошли от читателите.
Имам този VIEW, който предоставя фиктивен набор от данни за канали (нещо, което донякъде разбирам):
mysql> SELECT * FROM pipe_vw;
+---------+-------------+-----------+-------+-------------+------------+----------------+
| pipe_id | pipe_name | joint_num | heat | pipe_length | has_degree | wall_thickness |
+---------+-------------+-----------+-------+-------------+------------+----------------+
| 181 | Joint-278 | 39393A | 9111 | 17.40 | 1 | 0.393 |
| 182 | Joint-8819 | 19393Y | 9011 | 16.60 | 0 | 0.427 |
| 183 | Joint-9844 | 39393V | 8171 | 10.40 | 0 | 0.393 |
| 184 | Joint-2528 | 34493U | 9100 | 11.50 | 1 | 0.427 |
| 185 | Joint-889 | 18393z | 9159 | 13.00 | 0 | 0.893 |
| 186 | Joint-98434 | 19293Q | 8174 | 9.13 | 0 | 0.893 |
| 187 | Joint-78344 | 17QTT | 179 | 44.40 | 1 | 0.893 |
| 188 | Joint-171C | 34493U | 17122 | 9.45 | 1 | 0.893 |
| 189 | Joint-68444 | 17297Q | 6114 | 11.34 | 0 | 0.893 |
| 190 | Joint-4841R | 19395Q | 5144 | 25.55 | 0 | 0.115 |
| 191 | Joint-1224C | 34493U | 8575B | 15.22 | 1 | 0.893 |
| 192 | Joint-2138 | 34493C | 91 | 13.55 | 1 | 0.893 |
| 193 | Joint-122B | 34493U | 9100B | 7.78 | 1 | 0.893 |
+---------+-------------+-----------+-------+-------------+------------+----------------+
13 rows in set (0.00 sec)
Представете си, имам нужда от записите на активите на тръбите, представени в някакъв вид класиране на редове в зависимост от дължината на всяка отделна тръба. (Напр., най-дългата дължина е „маркирана“ като позиция номер 1, втората най-дълга дължина е „маркирана“ позиция 2 и т.н.)
Въз основа на описанието на функцията на прозореца RANK() в документацията:
„Връща ранга на текущия ред в рамките на неговия дял, с пропуски. Връстниците се считат за връзки и получават същия ранг. Тази функция не присвоява последователни рангове на партньорски групи, ако съществуват групи с размер, по-голям от един; резултатът е несвързани рангови номера ."
Изглежда, че е много подходящ за това изискване.
mysql> SELECT pipe_name, pipe_length,
-> RANK() OVER(ORDER BY pipe_length DESC) AS long_to_short
-> FROM pipe_vw;
+-------------+-------------+---------------+
| pipe_name | pipe_length | long_to_short |
+-------------+-------------+---------------+
| Joint-78344 | 44.40 | 1 |
| Joint-4841R | 25.55 | 2 |
| Joint-278 | 17.40 | 3 |
| Joint-8819 | 16.60 | 4 |
| Joint-1224C | 15.22 | 5 |
| Joint-2138 | 13.55 | 6 |
| Joint-889 | 13.00 | 7 |
| Joint-2528 | 11.50 | 8 |
| Joint-68444 | 11.34 | 9 |
| Joint-9844 | 10.40 | 10 |
| Joint-171C | 9.45 | 11 |
| Joint-98434 | 9.13 | 12 |
| Joint-122B | 7.78 | 13 |
+-------------+-------------+---------------+
13 rows in set (0.01 sec)
В следващия сценарий искам да надградя още повече предишния пример, като класирам записите от най-дълга към най-къса дължина, но за всяка отделна група от различни стойности wall_thickness.
Може би заявката и резултатите по-долу ще обяснят по-добре къде моята проза може да не е:
mysql> SELECT pipe_name, pipe_length, wall_thickness,
-> RANK() OVER(PARTITION BY wall_thickness ORDER BY pipe_length DESC) AS long_to_short
-> FROM pipe_vw;
+-------------+-------------+----------------+---------------+
| pipe_name | pipe_length | wall_thickness | long_to_short |
+-------------+-------------+----------------+---------------+
| Joint-4841R | 25.55 | 0.115 | 1 |
| Joint-278 | 17.40 | 0.393 | 1 |
| Joint-9844 | 10.40 | 0.393 | 2 |
| Joint-8819 | 16.60 | 0.427 | 1 |
| Joint-2528 | 11.50 | 0.427 | 2 |
| Joint-78344 | 44.40 | 0.893 | 1 |
| Joint-1224C | 15.22 | 0.893 | 2 |
| Joint-2138 | 13.55 | 0.893 | 3 |
| Joint-889 | 13.00 | 0.893 | 4 |
| Joint-68444 | 11.34 | 0.893 | 5 |
| Joint-171C | 9.45 | 0.893 | 6 |
| Joint-98434 | 9.13 | 0.893 | 7 |
| Joint-122B | 7.78 | 0.893 | 8 |
+-------------+-------------+----------------+---------------+
13 rows in set (0.00 sec)
Тази заявка използва клаузата PARTITION BY в колоната wall_thickness, защото искаме класирането (което ORDER BY pipe_length DESC предоставя), но ни е необходимо в контекста на отделните групи wall_thickness.
Класирането на всяка колона long_to_short се връща обратно на 1, когато срещнете (или промените) на различна стойност на колоната wall_thickness.
Нека се концентрираме върху резултатите от една единствена група.
При насочване към записите със стойности на wall_thickness 0,893, редът с pipe_length 44,40 има съответното long_to_short 'класиране' от 1 (това е най-дългият), докато редът с pipe_length 7,78 има съответстващо long_to_short 'класиране' от всички в рамките на това късо от 8 специфична група (0,893) стойности за дебелина на стената.
Функциите на прозореца са доста мощни и целият им обхват и широчина не биха могли да бъдат обхванати само в един раздел. Уверете се и посетете функциите на прозореца, поддържани в документацията на MySQL 8, за повече информация относно наличните в момента.
Подобрена пространствена поддръжка и възможности
Това е огромен набор от функции, включени в MySQL 8. Поддръжката на предишни версии или липсата на такава просто не можеше да се сравни с реализацията(ите) на други доставчици (помислете за PostGIS за PostgreSQL).
През последните 10 и повече години работих в областта като инспектор на тръбопроводи, събирайки GPS и данни за активи, така че тази група промени определено привлича вниманието ми.
Експертизата в областта на пространствените данни е изчерпателна тема сама по себе си и бъдете сигурни, че далеч не съм експерт по нея. Въпреки това се надявам да обобщя значителните промени между версии 5.7 и 8 и да ги предам по ясен и сбит начин.
Нека се запознаем с 2 ключови термина (и понятия) за целите на този раздел.
-
Пространствена референтна система или SRS - Ето частична дефиниция от Wikipedia:
„Пространствена референтна система (SRS) или координатна референтна система (CRS) е базирана на координати локална, регионална или глобална система, използвана за локализиране на географски обекти. системи."
-
Идентификатор на пространствена референтна система или SRID - Също така, Уикипедия има SRID, дефинирани като такива:
„Идентификаторът на пространствената референтна система (SRID) е уникална стойност, използвана за недвусмислено идентифициране на проектирани, непрожектирани и локални дефиниции на пространствена координатна система. Тези координатни системи формират сърцето на всички ГИС приложения.“
MySQL поддържа много типове пространствени данни. Един от най-често срещаните е ТОЧКА. Ако използвате вашия GPS, за да навигирате до любимия си ресторант, това местоположение е ТОЧКА на картата.
MySQL 5.7 третира почти всеки „пространствен обект ' като имащ SRID от 0, което е важно за изчисления. Тези изчисления се изчисляват в декартов тип координатна система. Всички обаче знаем, че нашият глобус е сфера и далеч не е плосък. Следователно във версия 8 имате възможност да го разглеждате като плосък или сферичен при изчисления.
Обратно към тези два термина, които дефинирахме по-рано.
Въпреки че 0 е SRID по подразбиране в MySQL версия 8, много (приблизително 5000+) други SRID се поддържат.
Но защо това е важно?
Това фантастично обяснение чрез публикацията в блога, Spatial Reference Systems в MySQL 8.0, го обобщава добре:
„По подразбиране, ако не посочим SRID, MySQL ще създаде геометрии в SRID 0. SRID 0 е понятието на MySQL за абстрактна, безединична, безкрайна катесова равнина. Докато всички други SRS се отнасят до някаква повърхност и дефинират единици за оси, SRID 0 не го прави."
По същество, когато извършвате изчисления с SRID, различни от SRID 0 , тогава формата на нашата Земя влиза в игра, разглежда се и влияе на тези изчисления. Това е от решаващо значение за всякакви смислени/точни изчисления. За задълбочен преглед и по-добра екстраполация вижте тази публикация в блога, обхващаща географията в MySQL 8.
Също така силно препоръчвам публикацията в блога на MySQL Server Team, Географски пространствени референтни системи в MySQL 8.0, за яснота относно SRS. Уверете се и го прочетете!
И накрая, за проблеми с надстройката на пространствените данни от версия 5.7 до 8, посетете някои от изброените тук несъвместими промени за повече информация.
Други забележителни наблюдения
По-долу са други подобрения на версията, които трябва да призная, въпреки че не са обхванати задълбочено в тази публикация в блога:
- utf8mb4 вече е наборът от знаци по подразбиране (по-рано latin1) – По-добра поддръжка за тях трябва да имат емоджи в допълнение към някои езици...
- Речник на транзакционни данни – MySQL метаданните вече се помещават в таблици на InnoDB.
- Невидими индекси – Задайте видимостта на индекс за оптимизатора, като в крайна сметка определяте дали добавянето или премахването му (индексът) е добро или лошо нещо. Добавянето на индекс към съществуваща голяма таблица може да бъде „скъпо ' по отношение на заключването и ресурсите.
- Низходящи индекси – По-добра производителност на индексирани стойности, които се съхраняват в низходящ ред.
- Колона за незабавно добавяне – За промени в схемата посочете ALGORITHM=INSTANT в изразите ALTER TABLE и (ако е възможно за операцията) избягвайте заключванията на метаданни. (За повече информация вижте тази страхотна публикация от екипа на MySQL Server и секцията ALTER TABLE от официалните документи.)
Бонус раздел:Нещо, което се надявах да видя...
Свързани ресурси ClusterControl за MySQL Станете серия от блогове на MySQL DBA – Общи операции – Промени в топологията на репликацията Станете серия от блогове на MySQL DBA – Надстройки на база данниОграниченията за проверка все още не са проникнали в продукта MySQL.
Както при предишните версии на MySQL, синтаксисът за проверка на ограничението е разрешен във вашите команди CREATE TABLE, но се игнорира. Доколкото ми е известно, повечето други доставчици на SQL поддържат ограничения за проверка. Елате да се присъедините към партито MySQL!
MySQL значително 'ускори ' предлагането му във версия 8. Поддържането на стабилни пространствени възможности, удобни опции за управление на потребители, „хибридни“ решения за SQL/NoSQL данни и аналитични функции сред многобройните допълнителни подобрения е наистина забележително.
Според мен с версия 8 MySQL продължава да предоставя солидна опция в непрекъснато растящата, конкурентна SQL екосистема с отворен код, пълна с подходящи и богати на функции решения.
Благодаря ви, че прочетохте.