Ponieważ większość, jeśli nie cały rok 2018 za nami (w zależności od tego, kiedy czytasz ten post), nie ma wątpliwości, że był to fantastyczny rok dla baz danych SQL o otwartym kodzie źródłowym.
Wydano zarówno PostgreSQL 11, jak i MySQL 8, zapewniając obu społecznościom wiele do „rozmawiania „. Prawdę mówiąc, obaj dostawcy wprowadzili wiele znaczących zmian i dodatków w swoich wydaniach i zasługują na pochwałę i wyróżnienia.
Zwykle gościnnie piszę o tym pierwszym na blogu Manynines (Wielkie podziękowania dla świetnej organizacji!), ale interesuje mnie też to drugie. Z wieloma wpisami na blogu na mojej własnej stronie internetowej (link w mojej sekcji bio), głównie ukierunkowanymi na MySQL w wersji 5.7, to (MySQL) jest zawsze na moich urządzeniach peryferyjnych.
Co więc ma MySQL 8, czego nie ma wersja 5.7? Jakie są ulepszenia? Cóż, jest ich wiele. W rzeczywistości jest zbyt wiele, by opisać je w jednym poście na blogu.
Niedawno zaktualizowałem do wersji 8 w moim obecnym środowisku uczenia się/rozwoju systemu Linux, więc pomyślałem, że spróbuję wskazać niektóre z nich.
Nie mogę zagwarantować dogłębnej dyskusji na temat Twojego „ulubionego ' Nowe funkcje). Z drugiej strony odwiedzę te, które przykuły moją uwagę albo przez osobiste zainteresowanie, albo przez wiele wspaniałych postów na blogach publikowanych przez cały rok w wersji 8.
MySQL staje się coraz lepszy... Wspaniałe ulepszenia w wersji 8!
Role
Dzięki rolom administratorzy baz danych mogą złagodzić nadmiarowość, w której wielu użytkowników będzie miało te same uprawnienia lub zestaw uprawnień.
Role są częścią standardu SQL.
Po utworzeniu określonej roli z żądanymi/wymaganymi uprawnieniami możesz następnie przypisać użytkownikom tę konkretną rolę za pomocą polecenia GRANT lub w podobny sposób „zabierz ' z REVOKE.
Role niosą ze sobą wiele korzyści i aby ułatwić sobie życie, istnieje kilka tabel, które pomogą Ci je śledzić:
-
mysql.role_edges - Tutaj znajdziesz te role i przypisanych do nich użytkowników.
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 — przechowuje wszystkie domyślne role i przypisanych użytkowników.
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)
Połączenie obu tabel (nie w sensie SQL JOIN) zasadniczo zapewnia „scentralizowaną lokalizację ' gdzie możesz:znać, monitorować i oceniać wszystkie wdrożone relacje i przypisania uprawnień do ról użytkownika.
Prawdopodobnie najprostszym scenariuszem wykorzystania roli byłoby:
Masz kilku użytkowników, którzy potrzebują „dostępu tylko do odczytu ' w określonej tabeli, co wymaga co najmniej uprawnienia SELECT. Zamiast przydzielać ją (SELECT) indywidualnie każdemu użytkownikowi, możesz ustanowić (utworzyć) rolę z tym uprawnieniem, a następnie przypisać tę rolę tym użytkownikom.
Ale role mają mały „haczyk „. Po utworzeniu i przypisaniu do użytkownika, użytkownik odbierający musi mieć ustawiony aktywny domyślny zestaw ról podczas uwierzytelniania po zalogowaniu.
Mówiąc o rolach i użytkownikach, uważam, że warto wspomnieć o zmianie zaimplementowanej w MySQL 8 dotyczącej komponentu validate_password, który jest wariantem wtyczki validate_password używanej w wersji 5.7.
Ten komponent udostępnia różne odrębne „kategorie ' sprawdzania hasła:niskie, średnie (domyślne) i silne. Odwiedź dokumentację komponentu validate_password, aby uzyskać pełny opis szczegółów walidacji każdego poziomu.
NoSQL mieszanie z SQL — magazyn dokumentów
Nadal uczę się tej funkcji, pomimo przelotnego zainteresowania MongoDB na początku 2016 roku. Do tej pory moje zainteresowania, badania i nauka koncentrowały się wyłącznie na „SQL”. Jestem jednak świadomy (poprzez dużo czytania w Internecie), że wielu jest podekscytowanych tego rodzaju strukturą (zorientowaną na dokument) przeplataną z „relacyjnym SQL” dostępnym teraz w magazynie dokumentów MySQL 8.
Poniżej znajduje się wiele korzyści dostępnych podczas korzystania z magazynu dokumentów. Pamiętaj i wspomnij o swoich ulubionych, które mogłem przegapić w sekcji komentarzy:
- Typ danych JSON jest obsługiwany od wersji MySQL 5.7.8, wersja 8 wprowadziła znaczące ulepszenia w pracy z JSON. Nowe funkcje specyficzne dla JSON wraz z „skrótem Operatory ', które mogą być używane zamiast wielu wywołań funkcji - z równymi wynikami/wyjściem.
- Być może jedną z głównych korzyści jest to, że nie musisz już wdrażać i pracować z wieloma rozwiązaniami baz danych, ponieważ NoSQL, SQL lub ich kombinacja są obsługiwane w magazynie dokumentów.
- „DevAPI” zapewnia płynne możliwości przepływu pracy w kontekście danych NoSQL (kolekcje i dokumenty). (Odwiedź oficjalną dokumentację podręcznika użytkownika DevAPI, aby uzyskać więcej informacji).
- Potężne sesje wiersza poleceń wykorzystujące Python, SQL lub JavaScript jako język powłoki.
- Zgodny z ACID.
- Szybko eksploruj i odkrywaj swoje dane bez definiowania schematu, tak jak w modelu relacyjnym.
Wspólne wyrażenia tabelowe (klauzula CTE lub WITH)
Co jeszcze możesz powiedzieć o CTE? Te rzeczy zmieniają zasady gry! Na początek, czym dokładnie jest popularne wyrażenie tabelowe?
Z Wikipedii:
„Zwykłe wyrażenie tabelowe lub CTE (w SQL) to tymczasowy nazwany zestaw wyników, pochodzący z prostego zapytania i zdefiniowany w zakresie wykonywania instrukcji SELECT, INSERT, UPDATE lub DELETE”.
Podam prosty przykład, demonstrując CTE. Jednak ich pełna moc nie jest wykorzystywana w tej sekcji, ponieważ istnieje wiele bardziej złożonych przykładów użycia niż te.
Mam prostą tabelę nazw z następującym opisem i danymi:
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)
Sprawdźmy, ile nazwisk zaczyna się na „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)
Wystarczająco łatwe.
Jednak używając klauzuli WITH, możesz „dostęp ' ten sam zestaw wyników zapytania (który można traktować jako tabelę pochodną) i odwoływać się do niego później w tej samej instrukcji - lub 'zakres ':
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)
Zasadniczo przypisuję nazwę do zapytania, umieszczając je w nawiasach. Następnie wybierz dane, które chcę z tego, co jest teraz ostatnim CTE_Z.
Last_Z CTE zapewnia pełny zestaw wyników, dzięki czemu można go jeszcze bardziej filtrować w ramach tego samego stwierdzenia:
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)
Kilka potężniejszych funkcji to „połączenie łańcuchowe ' wiele CTE razem i odniesienie do innych CTE w ramach CTE.
Oto przykład, który da ci pomysł (choć nie tak bardzo przydatny):
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)
W powyższym zapytaniu możesz zobaczyć, gdzie oddzieliłem CTE last_Z od CTE najlepszego_znajomego przecinkiem, a następnie umieściłem je w nawiasach po słowie kluczowym AS.
Zauważ, że mogę wtedy odnieść się do (i użyć) CTE last_Z, aby zasadniczo zdefiniować CTE best_friend.
Oto kilka powodów, dla których CTE są tak znaczącym ulepszeniem w wersji 8:
- Inni dostawcy SQL wspierali CTE (wielu od wcześniejszych wersji w ramach ich indywidualnego ekosystemu), a teraz MySQL 8 wypełnił lukę w tym obszarze.
- Standardowe włączenie SQL.
- W niektórych przypadkach (w stosownych przypadkach) CTE są lepszą opcją niż tabele tymczasowe, widoki, tabele pochodne (lub widoki wbudowane) i niektóre podzapytania.
- CTE może zapewnić „w locie ' zestaw wyników obliczeń, do którego można wysyłać zapytania.
- CTE może odwoływać się do samego siebie – znane jako rekurencyjne CTE (nie pokazano tutaj).
- CTE mogą nazywać i używać innych CTE
Funkcje okien
Zapytania analityczne są teraz możliwe w MySQL 8. Ponieważ funkcje Window nie są moją mocną stroną, skupiam się na bardziej dogłębnym badaniu i lepszym ich zrozumieniu, posuwając się do przodu. Te następne przykłady są w większości elementarne, zgodnie z moim rozumieniem. Sugestie, porady i sprawdzone metody są mile widziane od czytelników.
Mam ten WIDOK, który zapewnia fikcyjny zestaw wyników danych potoku (coś, co nieco rozumiem):
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)
Wyobraź sobie, że potrzebuję rekordów zasobów rur przedstawionych w pewnego rodzaju rankingu wierszy w zależności od długości każdej pojedynczej rury. (Np. najdłuższa długość to „oznaczona” pozycja numer 1, druga najdłuższa długość to „oznaczona” pozycja 2 itd.)
Na podstawie opisu funkcji okna RANK() w dokumentacji:
„Zwraca rangę bieżącego wiersza w jego podziale, z przerwami. Osoby równorzędne są uważane za remisy i otrzymują tę samą rangę. Ta funkcja nie przypisuje kolejnych rang do grup równorzędnych, jeśli istnieją grupy o rozmiarze większym niż jeden; wynikiem są niesąsiadujące numery rang ”.
Wygląda na to, że dobrze nadaje się do tego wymagania.
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)
W następnym scenariuszu chcę jeszcze bardziej rozwinąć poprzedni przykład, uszeregowując rekordy o długości od najdłuższej do najkrótszej, ale dla każdej indywidualnej grupy odrębnych wartości grubości_ściany.
Być może poniższe zapytanie i wyniki wyjaśnią lepiej, gdzie moja proza mogła nie mieć:
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)
To zapytanie używa klauzuli PARTITION BY w kolumnie wall_thickness, ponieważ chcemy rankingu (który zapewnia ORDER BY długość_rury DESC), jednak potrzebujemy go w kontekście poszczególnych grup wall_thickness.
Każdy ranking kolumny long_to_short resetuje się z powrotem do 1, gdy napotkasz (lub zmienisz) inną wartość kolumny wall_thickness.
Skoncentrujmy się na wynikach jednej grupy.
Kierując się na rekordy z wartościami grubości_ściany 0,893, wiersz o długości_rury 44,40 ma odpowiadający „ranking” długi_do_krótkiego równy 1 (jest najdłuższy), podczas gdy wiersz o długości_ruryki 7,78 ma odpowiadający „ranking” długi_do_krótkiej równy 8 (najkrótszy) konkretna grupa (0.893) wartości grubości_ściany.
Funkcje okien są dość potężne, a ich cały zakres i szerokość nie mogą być objęte pojedynczą sekcją. Pamiętaj i odwiedź Funkcje okna obsługiwane w dokumentacji MySQL 8, aby uzyskać więcej informacji na temat obecnie dostępnych.
Ulepszone wsparcie przestrzenne i możliwości
Jest to ogromny zestaw funkcji zawartych w MySQL 8. Obsługa poprzednich wersji lub jej brak, po prostu nie mogły się równać z implementacjami innych dostawców (pomyśl PostGIS dla PostgreSQL).
Od ponad 10 lat pracuję w terenie jako geodeta rurociągów, zbierając dane GPS i zasobów, więc ta grupa zmian zdecydowanie przyciąga moją uwagę.
Ekspertyza danych przestrzennych jest sama w sobie kompleksowym tematem i zapewniam, że daleko mi do eksperta w tej dziedzinie. Mam jednak nadzieję, że podsumuję znaczące zmiany między wersjami 5.7 i 8 i przekażę je w jasny i zwięzły sposób.
Zapoznajmy się z 2 kluczowymi terminami (i pojęciami) na potrzeby tej sekcji.
-
Spatial Reference System lub SRS — oto częściowa definicja z Wikipedii:
„System odniesienia przestrzennego (SRS) lub system odniesienia współrzędnych (CRS) to lokalny, regionalny lub globalny system oparty na współrzędnych, używany do lokalizowania jednostek geograficznych. Przestrzenny system odniesienia definiuje określoną projekcję mapy, a także przekształcenia między różnymi odniesieniami przestrzennymi systemy."
-
Spatial Reference System Identifier lub SRID — również Wikipedia ma zdefiniowany identyfikator SRID w następujący sposób:
„Identyfikator systemu odniesienia przestrzennego (SRID) to unikalna wartość używana do jednoznacznej identyfikacji rzutowanych, nierzutowanych i lokalnych definicji przestrzennych układów współrzędnych. Te układy współrzędnych stanowią serce wszystkich aplikacji GIS”.
MySQL obsługuje wiele typów danych przestrzennych. Jednym z bardziej powszechnych jest PUNKT. Jeśli używasz GPS do nawigacji do swojej ulubionej restauracji, wtedy ta lokalizacja jest PUNKTEM na mapie.
MySQL 5.7 obsługuje prawie każdy 'obiekt przestrzenny ' jako mający SRID równy 0, co jest istotne dla obliczeń. Obliczenia te są obliczane w układzie współrzędnych kartezjańskich. Jednak wszyscy wiemy, że nasz glob jest kulą i nie jest płaski. Dlatego w wersji 8 masz możliwość uznania jej za płaską lub sferyczną w obliczeniach.
Wracając do tych dwóch terminów, które zdefiniowaliśmy wcześniej.
Mimo że 0 jest domyślnym SRID w MySQL w wersji 8, wiele (około 5000+) innych SRID jest obsługiwanych.
Ale dlaczego to ważne?
To fantastyczne wyjaśnienie zawarte w poście na blogu, Spatial Reference Systems w MySQL 8.0, ładnie to podsumowuje:
„Domyślnie, jeśli nie określimy SRID, MySQL utworzy geometrie w SRID 0. SRID 0 jest pojęciem MySQL dotyczącym abstrakcyjnej, bezjednostkowej, nieskończonej płaszczyzny katezjańskiej. Podczas gdy wszystkie inne SRS odnoszą się do jakiejś powierzchni i określają jednostki dla osie, SRID 0 nie.
Zasadniczo podczas wykonywania obliczeń z użyciem SRID innych niż SRID 0 , wtedy kształt naszej Ziemi wchodzi w grę, jest rozważany i wpływa na te obliczenia. Ma to kluczowe znaczenie dla wszelkich znaczących/dokładnych obliczeń. Aby uzyskać dogłębne podsumowanie i lepszą ekstrapolację, zobacz ten wpis na blogu dotyczący geografii w MySQL 8.
Gorąco polecam również wpis na blogu MySQL Server Team, Geographic Spatial Reference Systems w MySQL 8.0, dla jasności co do SRS. Upewnij się i przeczytaj!
Wreszcie, w przypadku problemów z aktualizacją danych przestrzennych z wersji 5.7 do 8, odwiedź niektóre z niezgodnych zmian wymienionych tutaj, aby uzyskać więcej informacji.
Inne ważne uwagi
Poniżej znajdują się inne ulepszenia wersji, które muszę przyznać, chociaż nie są one szczegółowo omówione w tym poście na blogu:
- utf8mb4 jest teraz domyślnym zestawem znaków (wcześniej latin1) - Lepsza obsługa tych, które muszą mieć emotikony oprócz niektórych języków...
- Transakcyjny słownik danych – metadane MySQL są teraz przechowywane w tabelach InnoDB.
- Niewidoczne indeksy — Ustaw widoczność indeksu dla optymalizatora, ostatecznie określając, czy dodanie go lub usunięcie (indeks) jest dobre, czy złe. Dodanie indeksu do istniejącej dużej tabeli może być „drogie ' pod względem blokowania i zasobów.
- Descending Indexes - Lepsza wydajność indeksowanych wartości, które są przechowywane w porządku malejącym.
- Natychmiastowe dodawanie kolumny — w przypadku zmian schematu określ ALGORITHM=INSTANT w instrukcjach ALTER TABLE i (jeśli jest to wykonalne dla operacji) unikaj blokad metadanych. (Aby uzyskać więcej informacji, zobacz ten wspaniały post zespołu MySQL Server oraz sekcję ALTER TABLE w oficjalnych dokumentach.)
Sekcja bonusowa:coś, co miałem nadzieję zobaczyć...
Zasoby pokrewne ClusterControl for MySQL Seria blogów:Zostań administratorem MySQL DBA — Typowe operacje — Zmiany w topologii replikacji Seria blogów:Zostań administratorem bazy danych MySQL — Aktualizacje bazy danychSprawdź, czy ograniczenia nie zostały jeszcze wprowadzone do produktu MySQL.
Podobnie jak w poprzednich wersjach MySQL, sprawdzanie składni ograniczeń jest dozwolone w poleceniach CREATE TABLE, ale jest ignorowane. O ile mi wiadomo, większość innych dostawców SQL obsługuje ograniczenia kontrolne. Dołącz do imprezy MySQL!
MySQL znacznie „wzrósł ' jego oferta w wersji 8. Obsługa solidnych możliwości przestrzennych, wygodnych opcji zarządzania użytkownikami, 'hybrydowych' rozwiązań danych SQL/NoSQL oraz funkcji analitycznych wśród licznych dodatkowych ulepszeń, jest naprawdę godna uwagi.
Moim zdaniem, wraz z wersją 8, MySQL nadal stanowi solidną opcję w stale rosnącym, konkurencyjnym ekosystemie SQL typu open source, pełnym odpowiednich i bogatych w funkcje rozwiązań.
Dziękuję za przeczytanie.