sql >> Database teknologi >  >> RDS >> Mysql

MySQL i 2018:Hvad er i 8.0 og andre observationer

Med det meste, hvis ikke hele 2018 bag os (afhængigt af hvornår du læser dette indlæg), er der ingen tvivl om, at det var et fantastisk år for open source SQL-databaser.

PostgreSQL 11 og MySQL 8 blev begge udgivet, hvilket gav begge fællesskaber masser at 'tale om '. Sandt at sige har begge leverandører introduceret mange væsentlige ændringer og tilføjelser i deres respektive udgivelser og fortjener deres ros og anerkendelser.

Jeg plejer at gæste indlæg om førstnævnte her på Severalnines-bloggen (Mange tak til en fantastisk organisation!), men jeg har også en interesse i sidstnævnte. Med mange blogindlæg på min egen hjemmeside (link i min biosektion), for det meste rettet mod MySQL version 5.7, er den (MySQL) altid i min periferiudstyr.

Så hvad har MySQL 8, som version 5.7 ikke har? Hvad er forbedringerne? Nå, der er mange. Faktisk for mange til at dække i kun ét blogindlæg.

Jeg har for nylig opgraderet til version 8 i mit nuværende Linux-lærings-/udviklingsmiljø, så jeg tænkte på at prøve at pege på nogle af dem.

Jeg kan ikke garantere dig en dybdegående diskussion om din 'favorit ' nye funktioner). På den anden side vil jeg besøge dem, der har fanget min opmærksomhed enten via en personlig interesse eller gennem de mange fantastiske blogindlæg, der er offentliggjort i løbet af året på version 8.

MySQL bliver bedre og bedre...Fantastiske forbedringer i version 8!

Roller

Med roller kan DBA'er mindske redundans, hvor mange brugere vil dele det samme privilegium eller sæt privilegier.

Roller er en del af SQL-standarden.

Efter at have oprettet en specifik rolle med de ønskede/krævede privilegier, kan du derefter tildele brugere den pågældende rolle via GRANT-kommandoen eller på samme måde, 'tager væk ' med REVOKE.

Roller kommer med adskillige fordele, og for at gøre livet lidt nemmere er der et par tabeller, der hjælper dig med at holde styr på dem:

  • mysql.role_edges - Her finder du disse roller og de brugere, de er tildelt.

    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 - Gemmer alle standardroller og de brugere, der er tildelt.

    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)

Kombinationen af ​​begge tabeller (ikke i SQL JOIN-forstand) giver i det væsentlige en 'centraliseret placering ' hvor du kan:kende, overvåge og vurdere alle dine implementerede brugerrolleprivilegier og tildelinger.

Det enkleste eksempel på rollebrugsscenarie ville sandsynligvis være:

Du har flere brugere, der har brug for 'skrivebeskyttet adgang ' på en bestemt tabel kræver derfor mindst SELECT-privilegiet. I stedet for at give det (SELECT) individuelt til hver bruger, kan du oprette (oprette) en rolle, der har det privilegium, og derefter tildele den rolle til disse brugere.

Men roller kommer med en lille 'fangst '. Når først den er oprettet og tildelt en bruger, skal den modtagende bruger have et aktivt standardrollesæt under godkendelse ved login.

Mens det drejer sig om roller og brugere, føler jeg, at det er vigtigt at nævne ændringen implementeret i MySQL 8 vedrørende validate_password-komponenten, som er en variant af validate_password-plugin'et, der blev brugt i version 5.7.

Denne komponent giver forskellige distinkte 'kategorier ' af adgangskodekontrol:lav, medium (standard) og stærk. Besøg dokumentationen til validate_password-komponenten for at få en fuldstændig gennemgang af hvert niveaus valideringsspecifikationer.

NoSQL-blanding med SQL - Dokumentlageret

Denne funktion er en, jeg stadig lærer om, på trods af en flygtig interesse for MongoDB i begyndelsen af ​​2016. Til dato har min interesse, undersøgelse og læring udelukkende været fokuseret på 'SQL'. Jeg er dog klar over (gennem megen læsning på nettet), at mange er begejstrede for denne type strukturering (dokumentorienteret) sammenflettet med 'relationel SQL', der nu er tilgængelig i MySQL 8 dokumentlageret.

Nedenfor er mange fordele tilgængelige, når du bruger dokumentlageret. Vær sikker på og nævn dine favoritter, jeg måske er gået glip af i kommentarfeltet:

  • JSON-datatypen er blevet understøttet siden MySQL version 5.7.8, men version 8 introducerede betydelige forbedringer til at arbejde med JSON. Nye JSON-specifikke funktioner sammen med 'shorthand ' operatører, der kan bruges i stedet for flere funktionskald - med samme resultater/output.
  • Måske en af ​​de største fordele er, at du ikke længere behøver at implementere og arbejde med flere databaseløsninger, da NoSQL, SQL eller en kombination af de to understøttes i dokumentlageret.
  • En "DevAPI", giver problemfri workflow-funktioner i en NoSQL-datakontekst (samlinger og dokumenter). (Besøg den officielle DevAPI-brugervejledning for mere information).
  • Kraftfulde kommandolinjesessioner, der bruger Python, SQL eller Javascript som 'shell'-sproget.
  • ACID-kompatibel.
  • Udforsk og find hurtigt dine data uden at definere et skema, som du ville gøre i en relationel model.

Almindelige tabeludtryk (CTE'er eller WITH-klausulen)

Hvad kan du ellers sige om CTE'er? Disse ting er en game-changer! For det første, hvad er et almindeligt tabeludtryk egentlig?

Fra Wikipedia:

"Et almindeligt tabeludtryk eller CTE (i SQL) er et midlertidigt navngivet resultatsæt, der er afledt af en simpel forespørgsel og defineret inden for eksekveringsomfanget af en SELECT-, INSERT-, UPDATE- eller DELETE-sætning."

Jeg vil give et simpelt eksempel, der demonstrerer CTE'er. Deres fulde kraft er dog ikke udnyttet i dette afsnit, da der er mange mere komplekse use-case eksempler end disse.

Jeg har en simpel navnetabel med denne beskrivelse og data:

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)

Lad os finde ud af, hvor mange efternavne der starter med '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)

Nemt nok.

Men ved at bruge WITH-sætningen kan du 'adgang ' dette samme sæt forespørgselsresultater (som kan opfattes som en afledt tabel) og referer til det senere inden for samme sætning - eller 'omfang ':

 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)

Jeg tildeler dybest set et navn til forespørgslen, pakker den ind i parentes. Vælg derefter de data, jeg vil have, fra det, der nu er last_Z CTE.

Last_Z CTE giver et komplet resultatsæt, så du kan filtrere det endnu længere inden for samme sætning:

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)

Et par af de mere kraftfulde funktioner er 'kæde ' flere CTE'er sammen og refererer til andre CTE'er inden for CTE'er.

Her er et eksempel for at give dig en idé (selv om det ikke er så meget nyttigt):

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)

I ovenstående forespørgsel kan du se, hvor jeg adskilte last_Z CTE fra best_friend CTE med et komma og derefter indsatte forespørgslen i parentes efter AS-søgeordet.

Bemærk, at jeg så er i stand til at henvise til (og bruge) last_Z CTE til i det væsentlige at definere best_friend CTE.

Her er et par grunde til, at CTE'er er så væsentlig en forbedring i version 8:

  • Andre SQL-leverandører har understøttet CTE'er (mange siden tidligere versioner inden for deres individuelle økosystemer), og nu har MySQL 8 lukket hullet på dette område.
  • En standard SQL-inkludering.
  • I nogle tilfælde (hvor det er relevant) er CTE'er en bedre mulighed end midlertidige tabeller, visninger, afledte tabeller (eller indlejrede visninger) og nogle underforespørgsler.
  • CTE'er kan levere en 'on-the-fly ' beregningsresultatsæt, du kan forespørge efter.
  • En CTE kan referere til sig selv - kendt som en rekursiv CTE (ikke vist her).
  • CTE'er kan navngive og bruge andre CTE'er
ClusterControlSingle Console for hele din databaseinfrastrukturFind ud af, hvad der ellers er nyt i ClusterControlInstaller ClusterControl GRATIS

Vinduefunktioner

Analytiske forespørgsler er nu mulige i MySQL 8. Da vinduesfunktioner ikke er min stærke side, er jeg fokuseret på en mere dybdegående undersøgelse og en bedre forståelse af dem i det hele taget fremover. Disse næste eksempler er for det meste elementære efter min forståelse. Forslag, råd og bedste praksis er velkomne fra læsere.

Jeg har denne VIEW, der giver et fiktivt rørdataresultatsæt (noget jeg til en vis grad forstår):

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)

Forestil dig, jeg har brug for pipeaktivregistreringerne præsenteret i en slags rækkerangering afhængigt af længden af ​​hvert enkelt rør. (F.eks. er den længste længde "mærket" nummer 1-positionen, den næstlængste længde er "mærket" position 2 osv...)

Baseret på RANK() vinduesfunktionsbeskrivelsen i dokumentationen:

"Returnerer rangeringen af ​​den aktuelle række inden for dens partition med huller. Peers betragtes som bindinger og modtager den samme rang. Denne funktion tildeler ikke fortløbende rækker til peer-grupper, hvis der findes grupper af størrelse større end én; resultatet er ikke-sammenhængende rangnumre ."

Det ser ud til at være velegnet til dette krav.

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)

I det næste scenarie vil jeg bygge endnu mere på det foregående eksempel ved at rangere registreringerne af længste til korteste længder, men pr. hver enkelt gruppe af de forskellige wall_thickness-værdier.

Måske vil nedenstående forespørgsel og resultater forklare bedre, hvor min prosa måske ikke har:

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)

Denne forespørgsel bruger PARTITION BY-sætningen i wall_thickness-kolonnen, fordi vi ønsker rangeringen (som ORDER BY pipe_length DESC giver), men vi har brug for den i sammenhæng med de individuelle wall_thickness-grupper.

Hver long_to_short kolonnerangering nulstilles til 1, når du støder på (eller ændrer) til en anden wall_thickness kolonneværdi.

Lad os koncentrere os om resultaterne af en enkelt gruppe.

Målrettet mod posterne med wall_thickness-værdier på 0,893, har rækken med pipe_length 44,40 en tilsvarende long_to_short 'ranking' på 1 (det er den længste), mens rækken med pipe_length 7,78 har en tilsvarende long_to_short 'ranking' på 8 (den korteste) specifik gruppe (0,893) af wall_thickness-værdier.

Vinduesfunktioner er ret kraftfulde, og hele deres omfang og bredde kunne umuligt dækkes i ét afsnit alene. Vær sikker på og besøg de vinduesfunktioner, der understøttes i MySQL 8-dokumentationen for at få flere oplysninger om dem, der er tilgængelige i øjeblikket.

Forbedret rumlig støtte og muligheder

Dette er et enormt sæt funktioner inkluderet i MySQL 8. Tidligere versioners support, eller mangel på samme, kunne simpelthen ikke sammenlignes med andre leverandørers implementering(er) (tænk PostGIS for PostgreSQL).

I de sidste 10 plus år har jeg arbejdet i marken som Pipeline Surveyor, med at indsamle GPS- og aktivdata, så denne gruppe af ændringer fanger bestemt min opmærksomhed.

Geodataekspertise er et omfattende emne i sig selv, og vær sikker på, jeg er langt fra en ekspert på det. Jeg håber dog at opsummere de væsentlige ændringer mellem version 5.7 og 8 og formidle dem på en klar og kortfattet måde.

Lad os gøre os bekendt med 2 nøgletermer (og begreber) til formålet med dette afsnit.

  1. Spatial Reference System eller SRS - Her er en delvis definition fra Wikipedia:

    "Et rumligt referencesystem (SRS) eller koordinatreferencesystem (CRS) er et koordinatbaseret lokalt, regionalt eller globalt system, der bruges til at lokalisere geografiske enheder. Et rumligt referencesystem definerer en specifik kortprojektion, samt transformationer mellem forskellige rumlige referencer systemer."

  2. Spatial Reference System Identifier eller SRID - Wikipedia har også SRID'er defineret som sådan:

    "A Spatial Reference System Identifier (SRID) er en unik værdi, der bruges til utvetydigt at identificere projekterede, uprojekterede og lokale rumlige koordinatsystemdefinitioner. Disse koordinatsystemer udgør hjertet af alle GIS-applikationer."

MySQL understøtter mange rumlige datatyper. En af de mere almindelige er et PUNKT. Hvis du bruger din GPS til at navigere til din yndlingsrestaurant, så er denne placering et PUNKT på et kort.

MySQL 5.7 behandler stort set alle 'rumlige objekter ' som havende et SRID på 0, hvilket er signifikant for beregninger. Disse beregninger beregnes i et kartesisk koordinatsystem. Vi ved dog alle, at vores klode er en kugle og langt fra flad. Derfor har du i version 8 mulighed for at betragte det som enten fladt eller sfærisk i beregninger.

Tilbage til de to udtryk, vi definerede tidligere.

Selvom 0 er standard SRID i MySQL version 8, understøttes mange (ca. 5.000+) andre SRID'er.

Men hvorfor er det vigtigt?

Denne fantastiske forklaring via blogindlægget, Spatial Reference Systems i MySQL 8.0, opsummerer det fint:

"Som standard, hvis vi ikke specificerer et SRID, vil MySQL skabe geometrier i SRID 0. SRID 0 er MySQL's begreb om et abstrakt, enhedsløst, uendeligt, katesisk plan. Mens alle andre SRS'er refererer til en overflade og definerer enheder for akser, gør SRID 0 ikke."

I det væsentlige, når du udfører beregninger med SRID'er andre end SRID 0 , så kommer formen på vores Jord i spil, overvejes og påvirker disse beregninger. Dette er afgørende for enhver meningsfuld/nøjagtig beregning. For en dybdegående gennemgang og bedre ekstrapolering, se dette blogindlæg, der dækker geografi i MySQL 8.

Jeg anbefaler også stærkt MySQL Server Team blogindlægget, Geographic Spatial Reference Systems i MySQL 8.0, for at få klarhed over SRS'er. Sørg for at læse det!

Til sidst, for spørgsmål om opgradering af geografiske data fra version 5.7 til 8, kan du besøge nogle af de inkompatible ændringer, der er anført her, for at få flere oplysninger.

Andre bemærkelsesværdige observationer

Nedenfor er andre udgivelsesforbedringer, som jeg må anerkende, selvom de ikke er dækket i dybden i dette blogindlæg:

  • utf8mb4 er nu standardtegnsættet (tidligere latin1) - Bedre understøttelse af disse skal have emojis ud over nogle sprog...
  • Transactional Data Dictionary - MySQL-metadata er nu indeholdt i InnoDB-tabeller.
  • Usynlige indekser - Indstil synligheden af ​​et indeks for optimeringsværktøjet, og afgør i sidste ende, om tilføjelse eller fjernelse af det (indekset) er en god eller dårlig ting. Tilføjelse af et indeks til en eksisterende stor tabel kan være 'dyrt ' med hensyn til låsning og ressourcer.
  • Faldende indekser – Bedre ydeevne på indekserede værdier, der er gemt i faldende rækkefølge.
  • Instant Add Column - For skemaændringer skal du angive ALGORITHM=INSTANT i ALTER TABLE-sætninger og (hvis det er muligt for operationen) undgå metadatalåse. (For mere information, se dette fantastiske indlæg fra MySQL Server-teamet og afsnittet ÆNDRINGSTABEL fra de officielle dokumenter.)

Bonusafsnit:Noget, jeg havde håbet at se...

Relaterede ressourcer ClusterControl for MySQL Bliv en MySQL DBA-blogserie – Almindelige operationer – Replikeringstopologiændringer Bliv en MySQL DBA-blogserie – Databaseopgraderinger

Tjek begrænsninger er ikke kommet ind i MySQL-produktet endnu.

Som med tidligere MySQL-versioner, er tjek begrænsningssyntaks tilladt i dine CREATE TABLE-kommandoer, men det ignoreres. Så vidt jeg ved, understøtter de fleste andre SQL-leverandører check-begrænsninger. Kom og vær med til festen MySQL!

MySQL er markant 'trappet op ' dets tilbud i version 8. Understøttelse af robuste rumlige muligheder, praktiske muligheder for brugeradministration, 'hybride' SQL/NoSQL-dataløsninger og analytiske funktioner blandt de talrige yderligere forbedringer er virkelig bemærkelsesværdig.

Efter min mening, med version 8, fortsætter MySQL med at give en solid mulighed i det stadigt voksende, konkurrencedygtige open source SQL-økosystem, fuld af relevante og funktionsrige løsninger.

Tak fordi du læste med.


  1. Sådan skjuler du resultatsæt-dekoration i Psql-output

  2. Opret en pivottabel med PostgreSQL

  3. Beverly Hills 90210 og ZIP+4:Håndtering af adresser i datamodeller

  4. PostgreSQL 11 - Procedurer