Publikuj meta vs. oddzielne tabele bazy danych

29

Przy opracowywaniu wtyczek wymagających przechowywania danych, jakie są zalety i wady korzystania z tej lub innej metody?

Wyjaśnienie podane w kodeksie nie jest szczegółowo:

Zanim jednak przejdziesz do nowej tabeli, zastanów się, czy przechowywanie danych wtyczki w WordPress 'Post Meta (inaczej Custom Fields) będzie działać. Post Meta jest preferowaną metodą; używaj go, gdy jest to możliwe / praktyczne.

Nassif Bourguig
źródło
FYI: MB Custom Table to wtyczka, która może przechowywać metadane w niestandardowych tabelach zamiast post-meta tabeli WP.
Anh Tran,

Odpowiedzi:

30

Cóż, jeśli wezmę czapkę skryptu WP, moja odpowiedź brzmi: zawsze używaj post_meta.

Jednak zdarza mi się wiedzieć coś o bazach danych, więc moja odpowiedź brzmi: nigdy, nigdy, nigdy, nie używaj EAV (zwanej także tabelą post_meta) do przechowywania danych, które mogą być potrzebne do zapytania.

Na froncie indeksu w zasadzie nie warto używać w tabelach meta. Tak więc, jeśli przechowujesz typ danych XYZ i masz nadzieję, że wykonasz zapytanie do wszystkich postów, które mają XYZ o wartości 'abc', no cóż ... powodzenia. (Zobacz wszystkie bilety związane z użytkownikami / rolami / czapkami w WP trac, aby dać ci wyobrażenie o tym, jak krwawe może być.)

Na froncie łączenia szybko dochodzi do limitu, w którym optymalizator decyduje się na użycie ogólnego algorytmu zamiast analizy zapytania, gdy istnieje wiele kryteriów łączenia.

Zatem nie, nie, nie, nie. Nigdy, nigdy, nigdy, nigdy nie używaj meta. Chyba że to, co przechowujesz, jest kosmetyczne i nigdy nie będzie częścią kryteriów zapytania.

Rozkłada się na twoją aplikację. Jeśli przechowujesz, powiedzmy, datę urodzin reżysera, to wielka sprawa. Użyj meta, ile chcesz. Ale jeśli przechowujesz, powiedzmy, datę premiery filmu, zwariowałbyś, aby nie używać osobnej tabeli (lub dodawać kolumny do tabeli postów) i dodawać indeks do tej kolumny.

Denis de Bernardy
źródło
1
Tak, wtyczki, które opracowuję, obsługują niestandardowe dane, takie jak wydarzenia, wiadomości, komunikaty prasowe, oferty pracy ... Spoza „WordPress World” używanie tabel nie jest opcją. Jednak porady Kodeksu WordPress są nieco mylące. Jak można serializować fragmenty danych w porównaniu do danych znormalizowanych / ustrukturyzowanych / indeksowanych?
Nassif Bourguig,
1
Jeśli zapytasz przeciętnego dewelopera WP, prawdopodobnie odpowie „użyj meta” lub „użyj taksonomii”. I zgadzam się, do tego stopnia, że ​​musisz zapytać o to. Jeśli tak, i uważam, że to Twoja sprawa, moja jedyna odpowiedź brzmi: dodaj pola do tabeli postów lub utwórz całkowicie osobną tabelę. W przeciwnym razie masz ogromne problemy z wydajnością, jeśli chodzi o zapytania, a co ważniejsze w przypadku list węzłów, sortowanie od góry do góry.
Denis de Bernardy,
1
Denis, czy byłbyś w stanie rozwinąć tę kwestię nieco bardziej? Uważam, że jest to bardzo pouczające, ale chciałbym uzyskać więcej danych, czy ktoś przeprowadził testy ?, jakie dokładnie są główne wady i ograniczenia, dzięki.
Wyck,
6
@Denis - Dość namiętna rzecznictwo przeciwko postmeta, co? Wiesz, że zdecydowanie przeciwstawiasz się ortodoksji i wypadniesz z dobrych łask arcykapłanów kościoła poezji kodowej, jeśli wytrwacie w takich rozmowach, prawda? :-) Ale poważnie, nie sądzisz, że trochę zawyżasz? To naprawdę zależy od tego, czy będą dziesiątki tysięcy meta rekordów, czy nie. W wielu przypadkach po prostu nie ma wystarczającej liczby danych do zmartwienia. Jedna złożona witryna, którą wdrażam, zawiera około 10 000 meta rekordów z kilkoma nowymi planami i jest w porządku (fyi, to nie jest blog).
MikeSchinkel
1
@Denis - Dzięki za komentarze. I nie zrozumcie mnie źle, prawdopodobnie skłaniam się bardziej do twojej perspektywy, ale połączenie 1.) godzinnej debaty z Mattem na WordCamp Birmingham nad zaletami pól podobnych do Pods oraz 2.) prostoty meta zrezygnowałem, skupiając uwagę na innych kwestiach, które potencjalnie mogę zmienić. W WCB przyjechałem, zdając sobie sprawę, że dopóki Matt jest odpowiedzialny za to, że to się nie zmieni, ponieważ (tak sądzę) Matt jest tak zachwycony pomysłem mniejszej liczby tabel, że nie pozwoli sobie na rozpoznanie wad strony indeksowania na bajcie 768 klawisz. <westchnienie>
MikeSchinkel,
5

Jeśli twoja wtyczka będzie miała DUŻO danych, wp_postmetato NIE jest dobrym pomysłem, jak pokazano poniżej:

Biorąc za przykład WooCommerce, w sklepie z ~ 30 000 produktów będzie średnio, powiedzmy, ~ 40 post meta (atrybuty i wszystko) na produkt, 5 zdjęć produktu na produkt, co oznacza, że ​​będzie ~ 4 meta obrazu dla każdego obrazu:

30 000 produktów x 40 meta każdy = 1 200 000 wierszy wp_postmeta

+

30 000 produktów x 5 zdjęć każdy x 4 meta obrazu dla każdego = 600 000 wierszy wp_postmeta

Tak więc, mając zaledwie 30 000 produktów, oczekujesz 1 800 000 wierszy wp_postmeta.

Jeśli dodasz więcej właściwości do swoich produktów lub zdjęć produktów, liczba ta się pomnoży.

Problem z tym jest dwojaki:

  • Samodzielne dołączanie jest bardzo kosztowne w MySQL
  • wp_postmetatabela nie jest indeksowana, chyba że używasz późniejszych wersji mysql (tj. nie ma indeksu FULLTEXT dla meta_value)

Aby podać przykład z rzeczywistej sprawy:

SELECT meta_value FROM wp_postmeta WHERE meta_key LIKE '_shipping_city'

To wybiera miasto wysyłki ze wszystkich szczegółów zamówienia w ok. 3 sekundach na dedykowanym serwerze podstawowym, nawet jeśli jest 5–10 zamówień . Jest tak, ponieważ zapytanie jest uruchamiane z wp_postmetatabeli, która ma ~ 3 miliony wierszy w instalacji na żywo.

Nawet strona główna działa dość wolno, ponieważ motyw pobiera różne elementy wp_postmeta- suwaki, kilka wstawek recenzji, kilka innych meta. Ogólnie lista produktów jest bardzo powolna, wyszukiwania są podobnie powolne podczas umieszczania produktów na liście.

Nie można tego naprawić w żaden normalny sposób. Możesz umieścić Elastic Search na swoim serwerze i użyć wtyczki Elastic Search w Wordpress, możesz użyć redis / memcached, możesz użyć dobrej wtyczki pamięci podręcznej strony, ale w końcu pozostanie fundamentalny problem - pobieranie dowolnej ilości danych z rozdętego wp_postmetatabela będzie powolna, ilekroć to zrobisz. Na serwerze, na którym testowałem rozwiązanie, które wdrożyłem poniżej, wszystkie zostały zainstalowane i skonfigurowane poprawnie i zoptymalizowane, a strona działała poprawnie OK dla niezalogowanych użytkowników lub często wykonywanych zapytań od momentu uruchomienia wtyczek buforujących.

Ale w momencie, gdy zalogowany użytkownik próbował zrobić coś, co zwykle nie było wykonywane, albo crony, wtyczki buforujące lub inne narzędzie chciało pobrać rzeczywiste dane z bazy danych, aby je buforować lub zrobić cokolwiek innego, wszystko poszło powoli.

Więc spróbowałem czegoś innego:

Kodowałem małą wtyczkę, aby przenieść wszystkie meta produktu (postmeta dla produktu typu post ) do niestandardowej tabeli generowanej przez kod. Ta wtyczka wzięła wszystkie meta dla każdego postu i utworzyła tabelę, dodając każdą meta jako kolumny i wstawiając wartości do każdego wiersza. Przekształciłem format EAV w poziomy, płaski format relacyjny. Miałem też wtyczkę do usuwania postmeta ze wszystkich przeniesionych produktów ze wp_postmetastołu.

W tym momencie przeniosłem załącznik postmeta i meta wszystkich innych typów postów do własnych tabel.

Następnie podłączyłem się do get_(post_type)_metafiltra, aby zastąpić pobieranie metadanych i udostępniać je z nowych tabel niestandardowych.

Teraz to samo zapytanie z wcześniejszego okresu, którego pobranie zajęło ~ 3 sekundy, wp_postmetazajmuje ~ 0,006 sekundy. Strona zachowuje się tak, jakby była świeżą instalacją WP.

....................

Oczywiście, robienie rzeczy tak, jak Wordpress jest lepsze. To jest właściwie norma.

Jednak jest również oczywista wiedza, że ​​tabela EAV jest bardzo nieefektywna w skalowaniu. Jest nieskończenie elastyczny i pozwala przechowywać dowolne dane, ale cena za to jest wydajnością. To podstawowa kompromis.

W tym kontekście trudno jest powiedzieć komuś, kto zamierza zgromadzić masę danych, i - na wszelki wypadek - zapytać / wyszukać te dane, aby wp_postmetana pewno użyć tabeli. Hit wydajności będzie świetny.

Korzystanie z niestandardowych tabel pozwoli na gromadzenie danych i nadal będzie wystarczająco szybkie.

Podobnie jak Pippin Williams, twórca wtyczki Easy Digital Downloads, użyłby tabel niestandardowych, gdyby zaczął kodować swoją wtyczkę, jeśli zamierzasz stworzyć coś, co będzie używane przez długi czas lub gromadzić dużo danych, bardziej efektywne jest używanie własnych tabel, jeśli dobrze je zaprojektujesz.

Musisz upewnić się, że każdy inny programista wtyczek / dodatków ma sposób na podłączenie się do wtyczki w celu manipulowania danymi przed i po ich odzyskaniu. Jeśli to zrobisz, będziesz całkiem solidny.

jedność100
źródło
1
Interesujące rzeczy! Należy wyjaśnić, że wspomniany filtr „get_ (typ_typu) _meta” jest faktycznie nazywany „get_ (typ meta) _metadata”, gdzie meta-typ to post, komentarz lub użytkownik. Tak więc get_post_meta () przejdzie przez filtr get_post_metadata, niezależnie od typu postu. Zwracana wartość filtru to końcowa wartość meta.
Berend
get_ (meta-type) _metadata -> rzeczywiście działa ze wszystkimi typami postów, a rzeczywiście ostatnią funkcją, którą odwiedzamy, jest get_post_metadata. Filtr działa jednak, gdy go używasz.
jedność100
2

To zależy od tego, co robisz. Metoda WP polega na użyciu istniejących tabel, ponieważ zostały one zaprojektowane tak, aby były wystarczająco elastyczne, jednak od czasu do czasu można uzyskać nową klasę danych, których nie można umieścić w istniejącej tabeli, np. Jeśli chcesz metadanych kategorii , możesz utworzyć tabelę wp_termsmeta.

Zazwyczaj jednak możesz przechowywać swoje dane dość wygodnie w różnych istniejących tabelach, a miejsce przechowywania danych zależy od tego, co robi Twoja wtyczka.

  • Aby uzyskać ogólne ustawienia wtyczki, użyj wywołania API get_option () - to również zostanie zapisane w pamięci podręcznej.
  • Aby uzyskać ustawienia wtyczek, które dotyczą konkretnego posta, użyj niestandardowych metadanych dla posta za pomocą get_post_meta () . To zwykle wystarcza na to, czego potrzebujesz.

Buforowanie jest zaimplementowane w WordPress, aby przyspieszyć również czas reakcji.

Dan Smart
źródło
1

zgodził się z denis 100%. Ale jest na to sposób.

Problem z użyciem meta-postu do kwerend, które mają być sprawdzane, polega na tym, że wartości są tablicami itp. Tak jak to:

array(
'key1' => 'val 1',
'key2' => 'val 2'
);

Zostanie to zapisane w bazie danych jako szeregowy ciąg, który będzie wyglądał mniej więcej tak:

{array["key1"]...{}...}

Więc jeśli chcesz wysłać zapytanie do wszystkich postów, a array['key2'] = 'val 2'następnie wp musi pobrać każdy wpis meta o nazwie tablica, rozpakuj go, a następnie przetestuj, a następnie przejdź do następnego. Spowoduje to definitywne wyłączenie serwera, jeśli witryna odnosi sukcesy i zawiera wiele postów, stron, niestandardowych postów itp.

Rozwiązanie zależy od projektu, a zobaczysz dlaczego. Jeśli miałbyś zapisać dane jako a, var = valto wp będzie mógł wyszukiwać bez php rozpakowywania każdego testu. Aby to zrobić w powyższym scenariuszu, należy użyć przestrzeni nazw i przechowywać meta klucze:

_array_key1 = 'val 1';
_array_key2 = 'val 2';

wtedy wp szukając klucza 2 z val 2 będzie mógł go od razu wyciągnąć. Jest to jednak zależne od projektu. Mój obecny projekt opiera się na około 20 różnych typach danych, które mają być przechowywane z każdym niestandardowym postem, więc powyższe stworzy po prostu ogromną tabelę do przeszukania, widząc, jak oczekujemy setek tysięcy postów. Tak więc w tym scenariuszu niestandardowy stół jest jedynym sposobem.

Mam nadzieję, że to komuś pomoże

Daithí
źródło
0

Dla mojej strony FarmVille :) Zrobiłem obie, ale nigdy jej nie ukończyłem, ponieważ sprzedałem:

  1. Przeczytałem xml farmville i zrzuciłem dane do niestandardowej tabeli
  2. W WordPress miałem automatycznie tworzone pola niestandardowe dla każdego pola w tej tabeli (i kilka dodatkowych)
  3. Teraz martw się, co się stanie, jeśli wartość zmieni się w tabeli lub po drugiej stronie: pole niestandardowe, ponieważ muszą być stale zsynchronizowane

Zrobiłem to, ponieważ z jednej strony chciałem, aby użytkownicy edytowali witrynę Wordpress, wprowadzając nowe dane farmville, np. „Krowa kosztuje 10 monet” ALE od strony integracji: JEŚLI zmiana xml ment krowa kosztuje teraz „20 monet” (poprzez wtyczkę do edycji frontonu), która byłaby podana jako opcja po nim: aby XML LUB użytkownik miał rację (rodzaj systemu wiki).

Oto przykład użycia obu.

Edelwater
źródło