Jak typy danych i indeksy wpływają na prędkość działania i wydajność bazy danych

To w jakim formacie przechowujesz dane w bazie danych ma znaczenie. Ogromne. Mają też znaczenie indeksy. Właściwe połaczenie typów danych z indeksami jest kluczowe dla wydajności całej bazy danych. W testach poniżej mamy dwie proste tabele wypełnione pseudolosowymi danymi. Testy pokazują jak zmienia się prędkość wykonania zapytań w zależności od typów danych i obecności lub braku indeksów.

Testowe tabele

Utworzymy dwie proste tabele do testow; 'demo_table1' i 'demo_table2'. Obie tabele maja na celowo ustawiony typ danych varchar dla kolumny 'random_number' by zademonstrować różnice czasie wykonania zapytania dla różnych typów danych.

CREATE TABLE demo_table1 (
random_number VARCHAR(8),
random_text VARCHAR(100)
);

CREATE TABLE demo_table2 (
random_number VARCHAR(8),
random_text VARCHAR(100)
);

Wypełniamy tabele danymi

Umieszczamy pseudolosowe dane w testowych tabelach. W każdej tableli umieszczamy dwa miliony rekordów.

Tabela demo_table1:

Tabela 'demo_table2':

Test numer 1

Select z dwóch tabel z pomocą LEFT JOIN połączonych kluczem 'random_number' w obu tabelach. Kolumna 'random_number' przechowująca liczby z typem danych varchar, bez indeksów.

select
dt1.random_number
from demo_table1 dt1
join demo_table2 dt2
on dt1.random_number = dt2.random_number

Czas wykonania: 6.3 sekundy

Dodajemy indeksy do tabel

Dodanie indeksów do tabel prawdopodobnie znacząco przyśpieszy przygotwanie danych przez bazę danych. Dodajmy zatem indeksy dla kolumny 'random_number' w obu tabelach:

CREATE INDEX idx_random_number ON demo_table1 (random_number);
CREATE INDEX idx_random_number ON demo_table2 (random_number);

Test numer 2

Po dodaniu indeksów do tabel, select z dwoch tabel z pomocą LEFT JOIN i klucza 'random_number':

select

dt1.random_number

from demo_table1 dt1

join demo_table2 dt2

on dt1.random_number = dt2.random_number

 

Czas wykonania: 0.001 sekundy

 

Test numer 3

'Komplikujemy' bardziej zapytanie wstawiając warunek 'WHERE'. W poniższym zapytaniu MySQL automatycznie porówna '100' i '56798' jako liczbę.

select
dt1.random_number
from demo_table1 dt1
join demo_table2 dt2
on dt1.random_number = dt2.random_number
where dt1.random_number <= 100 and dt2.random_number < 56798

 

Czas wykonania: 0.6 sekundy 

 

Zmiana typu danych dla kolumny

Zmieniamy typ danych kolumny random_number na Integer dla obu tabel:

ALTER TABLE demo_table1
MODIFY COLUMN random_number INT;
ALTER TABLE demo_table1
MODIFY COLUMN random_number INT;

 

Usuwamy też indeksy:

DROP INDEX idx_random_number ON demo_table1 (random_number);
DROP INDEX idx_random_number ON demo_table2 (random_number);

 

Test numer 4

Zapytanie jak wcześniej - tym razem z typem danych Integer dla kolumny 'random_number' - bez indeksów

select
dt1.random_number
from demo_table1 dt1
join demo_table2 dt2
on dt1.random_number = dt2.random_number

 

Czas wykonania: 4.6 sekundy 

Dodajemy ponownie indeksy do tabel

Dodajmy zatem indeksy dla kolumny 'random_number' w obu tabelach:

CREATE INDEX idx_random_number ON demo_table1 (random_number);
CREATE INDEX idx_random_number ON demo_table2 (random_number);

Test numer 5

Ponowne wykonanie zapytania:

select
dt1.random_number
from demo_table1 dt1
join demo_table2 dt2
on dt1.random_number = dt2.random_number

 

Czas wykonania: 0.0 sekundy (milisekundy)

 

Test numer 6

'Komplikujemy' bardziej zapytanie wstawiając warunek 'WHERE'. W poniższym zapytaniu MySQL automatycznie porówna '100' i '56798' jako liczbę.

select
dt1.random_number
from demo_table1 dt1
join demo_table2 dt2
on dt1.random_number = dt2.random_number
where dt1.random_number <= 100 and dt2.random_number < 56798

 

Czas wykonania: 0.0 sekundy (milisekundy)

 

Wnioski

Użycie właściwych typów danych do przechowywania informacji ma znaczenie nawet jeśli nie używasz indeksów dla kolumn w tabelach. Zastosowanie indeksów jest kluczowe dla odpowiedniej wydajności bazy danych. Poniżej podsumowanie rezultatów testów. Weź pod uwagę że testy zostały wykonane na trywialnych ilościach danych i bardzo prostych zapytaniach. W realnym środowisku produkcyjnym różnice byłby ogromne.

 

Stan tabel: Czas wykonania zapytania:
varchar użyty do przechowania liczb, brak indeksów 6.3 sekundy
integer użyty do przechowania liczb, brak indeksów 4.6 sekundy [27.0% szybciej]
varchar użyty do przechowania liczb, indeksy 0.001 sekundy [99.98% szybciej]
integer użyty do przechowania liczb, indeksy 0.0 sekundy (wykonanie sql w milisekundach) [99.998% szybciej]