PDA

Zobacz pełną wersję : Problem z wydajnością



xeon235
02-12-2017, 13:40
Mam problem z wydajnością po przełączeniu tabel z myisam na innodb, w zasadzie problem dotyczy tylko tabeli #__categories (ok 4 tys rekordów), gdy ta tabela zostanie przełączona na innodb strona ładuje się po kilkanaście sekund.
Serwer: debian 9, nginx, mariadb (na starym serwerze apche i mysql 5.5 było to samo). Nie ma różnicy czy rozszezenia są włączone czy nie.

terra
02-12-2017, 13:51
4 tys. rekordów? masz tyle kategorii? To artykułów masz chyba kilkadziesiąt tysięcy ;) Na to potrzebujesz bazy klasy enterprise. InnoDB oferuje bardziej złożoną strukturę kluczy niż MyIsam (FOREIGN KEYS) i odżwieżanie kluczy jest niestety wolniejsze w InnoDB.

xeon235
02-12-2017, 13:58
Artykułów mam sporo mniej :) bo w kategoriach prezentowane sa produkty ze sklepu internetowego ktore sa wczytywane z innej bazy (wiem, troche pokrecone), o FOREIGN KEYS wiem, natomiast nie sadzilem ze przez to jest taka roznica wydajnosci, myslalem ze mozna to jakos rozwiazac ;(

moje
02-12-2017, 15:12
Którą wersję MariaDB masz?

Z częścią rzeczy MariaDB radzi sobie lepiej niż MySQL, warto by zajrzeć do jej konfiguracji.

Pomyśl nad przejściem na PostgreSQL, jeśli masz ją zindeksowaną, to hula jak marzenie.

xeon235
02-12-2017, 15:33
Z częścią rzeczy MariaDB radzi sobie lepiej niż MySQL, warto by zajrzeć do jej konfiguracji.

dlatego zostala wybrana MariaDB :)

konfiguracja wydaje sie ze jest zrobiona dobrze (nie robilem jej sam, a firma ktora zajmuje sie konfiguracja serwerow itd), wszystkie pozostale witryny po zmianach zaczely funkcjonowac o wiele wydajniej, problem dotyczy tylko tej jednej witryny i tej jedynej tabeli.

Co do wersji MariaDB:
MariaDB: 10.2.10-MariaDB-10.2.10+maria~stretch - mariadb.org
nginx: nginx/1.10.3
PHP: 7.0.19

mjmartino
02-12-2017, 19:49
Podepnij sobie dysk SSD drugi do instancji i tam przenieść bazę.
Lub zepnij w raid 0 a kopie wysyłaj gdzie indziej lub na storage obiektowy jak ta serwerowania posiada.
Ewentualnie można ograniczyć na stronach z problem ładowania kategorii które pewnie lądują się wszystkie, ograniczyć tylko do niezbędnych.

xeon235
02-12-2017, 20:14
tez nie :) mam dyski w rajdzie intela nvme

moje
02-12-2017, 22:52
A jak są pobierane dane z zewnętrznej bazy danych dla tej strony?

mjmartino
03-12-2017, 00:17
Pytanie a jak doszedłeś że to ta tabela ? i akurat baza nie wyrabia

xeon235
03-12-2017, 12:43
A jak są pobierane dane z zewnętrznej bazy danych dla tej strony?

uzytkownik bazy joomla ma uprawnienia dostepu do drugiej bazy, bo sa na tym samym serwerze i wykonywane jest zapytanie bezposrednio do "zewnetrznej" bazy - sprawdzalem z wlaczonym pobieraniem danych z zewnetrznej bazy i wylaczonym - roznicy nie ma

moje
03-12-2017, 12:52
To jeszcze napisz odpowiedź na pytanie @mjmartino.

xeon235
03-12-2017, 13:03
Pytanie a jak doszedłeś że to ta tabela ? i akurat baza nie wyrabia

Ponieważ po przełączeniu tabel na InnoDB odrazu widać było, że czas generowania strony wynosi dobre kilkanascie sekund, wiec zajrzalem do logow serwera i mysql zalogowal przykladowo nastepujace zapytanie jako long_query_time:


SELECT c.id, c.asset_id, c.access, c.alias, c.checked_out, c.checked_out_time, c.created_time, c.created_user_id, c.description, c.extension, c.hits, c.language, c.level,
c.lft, c.metadata, c.metadesc, c.metakey, c.modified_time, c.note, c.params, c.parent_id,
c.path, c.published, c.rgt, c.title, c.modified_user_id, c.version, CASE WHEN CHAR_LENGTH(c.alias) != 0 THEN CONCAT_WS(':', c.id, c.alias) ELSE c.id END as slug
FROM zfgey_categories as c
LEFT JOIN (SELECT cat.id as id FROM zfgey_categories AS cat JOIN zfgey_categories AS parent ON cat.lft BETWEEN parent.lft AND parent.rgt WHERE parent.extension = 'com_content' AND parent.published != 1 GROUP BY cat.id) AS badcats ON badcats.id = c.id
LEFT JOIN zfgey_categories AS s ON (s.lft <= c.lft AND s.rgt >= c.rgt) OR (s.lft > c.lft AND s.rgt < c.rgt)
WHERE (c.extension='com_content' OR c.extension='system') AND c.access IN (1,1,5) AND c.published = 1 AND badcats.id is null AND s.id=8
GROUP BY c.id, c.asset_id, c.access, c.alias, c.checked_out, c.checked_out_time,
c.created_time, c.created_user_id, c.description, c.extension, c.hits, c.language, c.level,
c.lft, c.metadata, c.metadesc, c.metakey, c.modified_time, c.note, c.params, c.parent_id,
c.path, c.published, c.rgt, c.title, c.modified_user_id, c.version
ORDER BY c.lft;

wiec przelaczylem #__categories spowrotem na myisam i strona ponownie zaczela funkcjonowac jak nalezy

moje
03-12-2017, 18:31
Zrób sobie tabelę, w której będziesz agregował dane z obu baz (przez jakieś api), pamiętaj o zoptymalizowaniu jej indeksów.

terra
04-12-2017, 10:57
InnoDB z definicji potrzebuje więcej pamięci niż MyISAM, a żeby działało szybciej to trzeba przeprojektować, strukturę tabel i przepływ danych w niej zawartych. Zapytanie, które prezentujesz nie należy do najprostszych i czytelnych. Może warto do niego usiąść i je uprościć.

csthomas
09-12-2017, 22:35
Powyższe zapytanie SQL jest dość pamięciożerne.
Póki co możesz odnaleźć miejsce gdzie jest generowane to zapytanie i wyrzucić kolumny po GROUP BY c.id.

Dla J3.8.x plik libraries/src/Categories/Categories.php:
Linia 294:


// Group by
$query->group(
'c.id, c.asset_id, c.access, c.alias, c.checked_out, c.checked_out_time,
c.created_time, c.created_user_id, c.description, c.extension, c.hits, c.language, c.level,
c.lft, c.metadata, c.metadesc, c.metakey, c.modified_time, c.note, c.params, c.parent_id,
c.path, c.published, c.rgt, c.title, c.modified_user_id, c.version'
);


zmień na:


// Group by
$query->group(
'c.id'
);

Ten prosty zabieg powinien wystarczyć na początek.