Dzisiejszy wpis jest po raz pierwszy inspirowany komentarzem jednego z Czytelników. Miałem wczoraj niemały powód do radości, bo Adam podsunął mi całkiem ciekawy temat o którym kiedyś już czytałem, ale tak jakoś wypadł mi z głowy i o nim nie napisałem. Co takiego mam na myśli? Coś bardzo ciekawego… ;]

Wstęp.

Jeden z najlepszych skryptów blogowych na świecie, na którym stoi także mój własny blog, a któremu na imię WordPress, oferuje bardzo interesującą funkcjonalność znaną jako wersje postów, lub też ich rewizje [post versions / post revisions]. Polega ona na tym, że w każdym momencie, kiedy klikamy w przycisk “podejrzyj” podczas edycji wpisu, zapisujemy kolejną wersję szkicu lub też po prostu aktualizujemy opublikowany już wpis, w bazie danych dodawany jest kolejny rekord z jego aktualnymi danymi.

O ile jest to bardzo przydatne w przypadku osób niezdecydowanych, które lubią wracać do starych wersji i patrzeć jak tekst ewoluował do finalnej, opublikowanej treści [mogą być to też osoby o innych upodobaniach, ale w tym wpisie będę krytyczny wobec samej idei rewizji, bo rozwiązanie prowadzi do ich usunięcia / zablokowania ;]], o tyle musimy mieć na uwadze konsekwencje, które rodzi nadmierne wykorzystywanie tychże.

Pierwszą i najbardziej zauważalną konsekwencją jest nieproporcjonalny wzrost rozmiaru bazy danych w porównaniu do ilości wpisów, jakie publikujemy na blogu. Kilka wersji tego samego postu ze zmienionymi kilkoma literkami dla “dopieszczenia” jego treści to kilkakrotnie większa ilość danych, które “gdzieś” muszą zostać zapisane. Załóżmy, że bloger, podobnie jak ja, nieustraszenie zbliża się do liczby 100 wpisów, z których każdy zawiera, załóżmy około 2000 znaków / bajtów. Niech każdy wpis ma tylko dwie [a jak wspomniał Adam w swoim komentarzu, zdarza się jemu mieć i 20 takowych] nadmiarowe rewizje, a rozmiar bazy danych który normalnie wynosiłby:

100 * 2000B ~ 100 * 2kB = 200kB
będzie wynosił:
100 * 2000B + 100 * 2000B * 2 ~ 100 * 2kB + 100 * 2kB * 2 = 300kB
czyli 3 razy więcej. Dość wspomnieć, że moja baza danych, która zawiera “trochę” mniej niż 100 wpisów ma już prawie 6MB. Oczywiście nie wszystkie dane odpowiadają za treść postów, aczkolwiek na pewno jest to lwia część tej liczby.

Drugą konsekwencją jest spowolnienie działania serwisu. Myślę, że dla każdego logiczny jest fakt stopniowo dłuższego wyszukiwania odpowiednich danych w coraz większym zbiorze informacji. Jeśli próbujesz wyciągnąć z pudełka czerwoną kulkę spośród dziesięciu innych, prawdopodobnie zauważysz ją po kilku sekundach, jeśli tych kulek będzie już sto, to “grzebanie” w pudełku będzie trwało minutę lub dłużej. Baza danych na szczęście nie potrzebuje aż tak długiego czau na poszukiwania, ale zwiększenie czasu wykonania zapytania z 100ms do 500ms powoduje istotne wrażenie “obciążenia” strony internetowej, którego, jako profesjonalni programiści / webmasterzy pragniemy raczej uniknąć [nasz Czytelnik, nasz Pan! ;]].

Oczywiście istnieją też inne konsekwencje, aczkolwiek te, które opisałem powyżej należą do najbardziej istotnych i “dotykających” największą liczbę użytkowników.

Znając mnie z poprzednich piątkowych wpisów pewnie nawet się nie zastanawiacie, czy jest na to rada, bo chyba udało mi się Was przyzwyczaić do tego, że nie odchodzicie z kwitkiem podczas zgłoszenia problemu. Szczerze mówiąc, to zastanawiam się, czy w ogóle czytacie w moich wpisach jakiekolwiek rozdziały poza “Rozwiązaniem” - we “Wstępie”, “Podsumowaniu” i im podobnych prawdopodobnie produkuję się na darmo, ale trudno - po prostu lubię ten styl “kompletnego” załatwienia sprawy. ;]

Rozwiązanie.

Zanim podam odpowiednie rozwiązanie, musimy sobie zadać pytanie, jaki jest problem, tj. co dokładnie chcemy osiągnąć w przypadku zarządzania tytułowymi rewizjami postów. W przypadku naszego charakteru mamy kilka opcji do wyboru:
  • nerwus - usuwa wszystkie rewizje i blokuje ich powstawanie, liczy się tylko aktualna wersja wpisu
  • czyściciel - po prostu usuwa wszystkie rewizje, ale chce, żeby jednak dalej były tworzone, taka okresowa “czystka” bazy danych
  • prezes - istniejące rewizje zostawia jako aktywa [lub pasywa, nie znam się ;]] firmy, ale chce, żeby w kolejnych wpisach liczba wersji była ograniczona do konkretnej liczby, no bo jak to, prezes, a nie kontroluje?
Popuściłem nieco wodze fantazji, ale spokojnie, już wracamy na Ziemię. Problem można rozwiązać na kilka sposobów, których połączenie daje nam wyżej wymienione “charaktery”:
  1. usunięcie wszystkich istniejących rewizji
  2. zablokowanie powstawania nowych rewizji
  3. ustalenie limitu rewizji dla wpisów
Zobaczmy więc, co możemy poradzić w każdej z wymienionych kwestii.

Usunięcie wszystkich istniejących rewizji.

WAŻNE: Przed wykonaniem jakichkolwiek opisanych niżej operacji zrób kopię zapasową bazy danych! W żadnym wypadku nie odpowiadam za dane utracone w chwili wykonania poniższych instrukcji!

Rewizje wpisów znajdują się w bazie danych razem z wpisami w tabeli wpposts [zakładam, że prefiks tabel przy instalacji WordPressa to właśnie wp, w przeciwnym wypadku musicie wstawić własny]. Jedyne, co odróżnia je od “normalnych” wpisów, to status “revision” w polu post_status, stąd skasowanie wszystkich rewizji dla wpisów i stron w najprostszej postaci to proste zapytanie DELETE do bazy danych:

DELETE FROM wp_posts
WHERE post_type = "revision";

Nie usunie to jednak wszystkich danych dotyczących tych wpisów, takich jak specyficzne dla rekordu metadane i przypisane taksonomie [kategorie, tagi, itp.]. Poniższe zapytanie do bazy danych ostatecznie rozprawi się z rewizjami uwzględniając także takie informacje:

DELETE ps, tr, pm
FROM wp_posts ps
LEFT JOIN wp_term_relationships tr ON ps.ID = tr.object_id
LEFT JOIN wp_postmeta pm ON ps.ID = pm.post_id
WHERE ps.post_type = "revision"

Zablokowanie powstawania nowych rewizji.

Aby zablokować powstawanie nowych rewizji, należy najpierw zapoznać się z plikiem wp_config.php. Znajdziecie go w katalogu głównym WordPressa, także bez paniki. W tym systemie jest wiele “hacków” [haków?] - sztuczek, bez znajomości których ciężko będzie poradzić sobie z naszym problemem.

Jedną z tych sztuczek jest informacja o istnieniu stałej WP_POST_REVISIONS. Może ona przyjmować wiele wartości, aczkolwiek żeby zmusić WP do osiągnięcia naszego celu musi przyjąć jedną z wcześniej ustalonych. Dla każdego podanego poniżej rozwiązania należy wstawić odpowiednią linijkę na końcu pliku wp_config.php:

W przypadku, kiedy chcemy wyłączyć powstawanie nowych rewizji, należy ustawić ją na “0”, bądź “false”:

define('WP_POST_REVISIONS', false);

lub:

define('WP_POST_REVISIONS', 0);

Ustalenie limitu rewizji dla wpisów i stron.

Jeśli jednak chcielibyśmy, żeby rewizje powstawały, ale w ograniczonej ilości, musimy ponownie wykorzystać naszą wspaniałą stałą WP_POST_REVISIONS. Jak zapewne się domyślacie, jej wartość musi być liczbą określającą ilość rewizji [jeśli pożądane są 3 rewizje na wpis]:

define('WP_POST_REVISIONS', 3);

Rozwiązanie dla Adama.

W Twoim przypadku, Adamie, należy wykonać instrukcje zawarte w punkcie 1. i 3., tj. usunięcie istniejących rewizji i ustalenie limitu rewizji dla każdego postu - jest to połączenie charakterów nerwusa i prezesa. ;] Spójrz też na początek rozdziału Podsumowanie, jeśli nie chcesz bawić się w edycję kodu.

Zaznaczam jednak, żebyś koniecznie zrobił kopię bazy danych, ponieważ zapytania, które podałem, znalazłem na formach / blogach w Internecie i teoretycznie [na tyle, na ile jestem w stanie zasymulować w głowie ich działanie] powinny one rozwiązać Twój problem. Będę wdzięczny za informacje na temat ewentualnych skutków wprowadzenia w życie moich porad.

To by było na tyle w kwestii całościowego rozwiązania. ;]

Podsumowanie.

Ten wpis nie obejmuje całości kwestii zarządzania rewizjami wpisów - istnieje wiele wtyczek do WordPressa, które umożliwiają bezproblemową zmianę odpowiednich ustawień bez edycji kodu - w wyszukiwarce wtyczek w katalogu WP należy tylko wpisać “post revisions” i zostaniemy zarzuceni wieloma pozycjami, z których każda kusi swoimi funkcjonalnościami.

Kończąc już dzisiejszy wpis chciałbym jeszcze raz podziękować Adamowi za wskazanie ciekawego problemu do rozwiązania. Chciałbym także zaprosić Was do zgłaszania spraw, przy których mógłbym pomóc - dla mnie to czysta przyjemność, kolejne doświadczenia i zwyczajna radość z tego, że po raz kolejny “nasi górą”, a dla Was realny czas oszczędzony na rzeczach, które Was nie interesują / których nie znacie / itp. ;] Do zobaczenia wkrótce!