Više nije uvek bolje
Ako pogledamo neke parametre poput sort buffer-a ili innodb buffer-a što je bafer veći to su performanse bolje, ono što je pogrešno je da takav princip primenimo na „sve“ paramtre .. ako pogledamo parametre koji definišu potrošnju resursa „po tredu“, setovanje join buffer-a na primer ili read rnd buffer-a na preveliku vrednost može dovesti do usporenja celog sistema zbog prevelikih tredova.
Nepravilno korištenje TEXT polja
Videli smo klijente koji postave max_heap_table_size i tmp_table_size na velike vrednosti da bi izbegli broj privremenih tabela kreiranih na disku. U 99% slucajeva ove velike vrednosti ne sluze nicemu i ne pomazu posto ce mysql privremene tabele uvek kreirati na disku u slucaju da:
- postoji TEXT ili BLOB polje u tabeli
- postoji polje u GROUP BY ili DISTINCT klauzuli koje je vece od 512 bajtova (racunajte da utf8mb4 uvek trosi 3 bajta po karakteru)
- postoji bilo koja kolona veca od 512 bajtova u SELECT listi ako se koristi UNION ili UNION ALL
Ako uzmemo da je TEXT limitiran na 64K isto kao i VARCHAR, poenta koristenje TEXT polja je ?! i jednostavno menjanje tipa polja u tabeli iz TEXT u VARCHAR resava problem sporih privremenih tabela na disku
Veličina je bitna
Često vidimo „preduvane“ i „prevelike“ baze podataka. Ljudi ne razmisljaju i misle da „predimenzionisana“ polja trose samo disk, a disk je jeftin; to nije tacno – trose i RAM a rama nikad dovoljno. Pogledajmo primer tabele:
CREATE TABLE `MyTest` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`name` varchar(255) DEFAULT NULL,
`type` bigint(20) DEFAULT NULL,
`createdate` datetime DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `myidx` (`name`,`type`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_520_ci;
ID polje koje je BIGINT ce zauzeti 8 bajtova, dakle ako vasa baza ima 1M slogova primarni kljuc ce zauzeti 7.6M, ako prebacimo to polje u INT (4 bajta) ceo index ce biti 3.8M. Sa vecim brojem slogova ova razlika raste, na 10M slogova u 10 razlicitih tabela samo na ovaj nacin ce te sacivati 380M. Ne samo da je prostor na disku sacuvan, umanjenjem velicine indexa veca je sansa da ce isti stati u innodb buffer pool / ostati u memoriji / omoguciti jos necemu da ostane u memoriji.
Obratite pažnju na statemente koji porede INT i CHAR
mysql> select * from MyTest where name =1234;
mysql> select * from MyTest where number =’1234′;
Oba selecta su sintaksno ispravna ali da li su i semanticki ispravna. Da li je polje name numerickog ili tekstualnog tipa? Da li je polje number numerickog ili tekstualnog tipa. Predjenje integera i char-a moze da zavrsi „cudnim“ posledicama po vasu aplikaciju.
Prazan LEF JOIN
SELECT a.var, b.var FROM a LEFT JOIN b ON a.id=b.id WHERE b.var = ‘xxx’
Ako setujete vrednost u tabeli b, left join ne smisla.
SELECT a.var1, a.var2 FROM a LEFT JOIN b ON a.id=b.id where a.var1 = ‘xxx’
Koja je poenta joina sa b?
#1 problem je uvek IO, spindlovi, ne kapacitet
Ako gledamo na DB performanse, disk je „najbitniji“. Razdvajanje OS-a, indexa, podataka, na razlicite „particije“ je beskorisno … razmestite podatke po spindlovima (spindl je fizicki hard disk, ne logicka particija). Cesta greska je tretiranje „particija“ umesto „spindlova“… razdvajanje log-a, data, index-a po particijama nece pomoci pri IO zagusenju, to je samo logicko razdvajanje i ne utice na performanse, razdvajanje po spindlovima povecava IO mogucnosti – samim tim povecava performanse…