Опубликовать мета против отдельных таблиц базы данных

29

При разработке плагинов, требующих хранения данных, каковы преимущества и недостатки использования того или иного метода?

Объяснение в кодексе не подробно:

Однако, прежде чем переходить к совершенно новой таблице, подумайте, сработает ли сохранение данных вашего плагина в пост-мета WordPress (он же Пользовательские поля). Post Meta является предпочтительным методом; используйте его, когда это возможно / практично.

Нассиф Бургиг
источник
К вашему сведению: MB Custom Table - это плагин, который может хранить метаданные в пользовательских таблицах вместо мета-таблицы WP.
Ань Чан

Ответы:

30

Ну, если я возьму шляпу детектива из WP скрипта, мой ответ будет таким: всегда используйте post_meta.

Однако я случайно кое-что знаю о базах данных, поэтому мой ответ таков: никогда, никогда, никогда не используйте EAV (он же таблица post_meta) для хранения данных, которые вам могут понадобиться для запроса.

Что касается индекса, то в мета-таблицах нет ничего, что стоило бы использовать. Итак, если вы храните тип данных XYZ и надеетесь, что вы запросите все сообщения с XYZ со значением 'abc', ну ... удачи. (См. Все тикеты, связанные с пользователями / ролями / шапками, в WP trac, чтобы дать вам представление о том, насколько он хорош.)

На фронте соединения вы быстро сталкиваетесь с пределом, при котором оптимизатор решает использовать общий алгоритм вместо анализа запроса при наличии нескольких критериев соединения.

Таким образом, нет, нет, нет, нет. Никогда, никогда, никогда не используйте мета. Если то, что вы храните, не является косметическим и никогда не будет частью критериев запроса.

Это ломается к вашему приложению. Если вы храните, скажем, дату рождения режиссера, тогда ничего страшного. Используйте мету все, что вы хотите. Но если вы храните, скажем, дату выпуска фильма, вы бы с ума сошли, если бы не использовали отдельную таблицу (или не добавили столбцы в таблицу публикаций) и не добавили индекс к этому столбцу.

Дени де Бернарди
источник
1
Да, плагины, которые я разрабатываю, обрабатывают пользовательские данные, такие как события, новости, пресс-релизы, предложения о работе ... Из-за пределов «WordPress World» использование таблиц на самом деле не вариант. Но совет от WordPress Codex немного сбивает с толку. Как сериализованные порции данных могут быть предпочтительнее, чем нормализованные / структурированные / индексированные данные?
Нассиф Бургиг
1
Если вы спросите среднестатистического разработчика WP, он, скорее всего, ответит «использовать мета» или «использовать таксономию». И я согласен, до того момента, когда вам нужно сделать запрос против этого. Если это так, и я полагаю, что это ваш случай, мой единственный ответ - добавить поля в таблицу сообщений или полностью создать отдельную таблицу. В противном случае вас ждут огромные проблемы с производительностью, когда речь идет о запросах и, что еще более важно, о списках узлов, сортировке по топ-n.
Дени де Бернарди
1
Денис, не могли бы вы подробнее остановиться на этом, я нахожу это очень информативным, но хотел бы получить больше данных, кто-нибудь делал тесты? Какие именно недостатки и ограничения, спасибо.
Вик
6
@ Денис - довольно страстная защита против постмета, а? Вы знаете, что вы идете вразрез с православием, и вы выпадете из добрых милостей первосвященников церкви поэзии кодекса, если вы будете настойчивы в таких разговорах, не так ли? :-) А если серьезно, разве ты не думаешь, что немного преувеличила? Это действительно зависит от того, будут ли десятки тысяч мета-записей или нет. Во многих случаях просто не хватает записей для беспокойства. Один сложный сайт, который я развертываю, содержит около 10 000 мета-записей с запланированными несколькими новыми записями, и это нормально (кстати, это не блог.)
MikeSchinkel
1
@ Денис - Спасибо за комментарии. И не поймите меня неправильно, я, вероятно, гораздо больше склоняюсь к вашей перспективе, но сочетание 1.) часовой дискуссии с Мэттом в WordCamp Бирмингеме о достоинствах полей, похожих на Pods и 2.) простоты мета должен был уйти в отставку, чтобы сосредоточить свое внимание на других вопросах, которые я мог бы потенциально изменить. В WCB я ушел, понимая, что пока Мэтт отвечает, он не изменится, потому что (я думаю, что) Мэтт настолько очарован идеей меньшего количества таблиц, что не позволит себе распознать отрицательные стороны индексации на 768 байт. ключ. <вздох>
MikeSchinkel
5

Если ваш плагин будет иметь много данных, то использование wp_postmetaНЕ является хорошей идеей, как показано ниже:

Если взять в качестве примера WooCommerce, в магазине с ~ 30 000 товаров будет в среднем, скажем, ~ 40 пост-мета (атрибуты и все) на продукт, 5 изображений товара на продукт, что означает ~ 4 мета изображения для каждого изображения:

30000 продуктов х 40 мета каждый = 120000 строк в wp_postmeta

+

30 000 товаров x 5 изображений каждый x 4 мета изображения для каждого = 600 000 строк в wp_postmeta

Таким образом, имея всего 30 000 продуктов, вы получаете 1,800 000 строк wp_postmeta.

Если вы добавите больше свойств к своим продуктам или изображениям продуктов, это число умножится.

Проблема с этим двоякая:

  • Самостоятельные объединения очень дороги с MySQL
  • wp_postmetaтаблица не индексируется, если вы не используете более поздние версии mysql (т. е. нет индекса FULLTEXT для meta_value)

Чтобы привести пример из реального случая:

SELECT meta_value FROM wp_postmeta WHERE meta_key LIKE '_shipping_city'

При этом выбирается город доставки из всех деталей заказа, что длится ~ 3 секунды на выделенном сервере начального уровня, даже если есть 5-10 заказов . Это связано с тем, что запрос выполняется из wp_postmetaтаблицы с ~ 3 миллионами строк в оперативной установке.

Даже домашняя страница идет довольно медленно, потому что тема извлекает различные элементы wp_postmeta- слайдеры, несколько вставок обзора, несколько других мета. В целом, список товаров очень медленный, поиск товаров аналогично медленен.

Вы не можете исправить это любым нормальным способом. Вы можете разместить Elastic Search на своем сервере и использовать плагин Elastic Search в Wordpress, вы можете использовать redis / memcached, вы можете использовать хороший плагин для кэширования страниц, но в итоге фундаментальная проблема останется - получение любого объема данных из раздутого wp_postmetaстол будет медленным, когда это будет сделано. На сервере, где я тестировал решение, которое реализовал ниже, все они были установлены и настроены должным образом и оптимизированы, и сайт работал удовлетворительно нормально для пользователей, не вошедших в систему или часто выполняющих запросы, так как подключались плагины кэширования.

Но в тот момент, когда вошедший в систему пользователь попытался сделать что-то, что обычно не выполнялось, или cron, плагины для кэширования или любая другая утилита захотели получить фактические данные из базы данных для кеширования или сделать что-то еще, все пошло не так, как надо.

Поэтому я попробовал что-то еще:

Я написал небольшой плагин для переноса всей мета продукта (postmeta для продукта типа post ) в пользовательскую таблицу, созданную кодом. Этот плагин взял все мета для каждого поста и создал таблицу, добавив каждую мету в виде столбцов и вставив значения в каждую строку. Я превратил формат EAV в горизонтальный, плоский реляционный формат. У меня также был плагин для удаления постмета из всех перемещенных продуктов из wp_postmetaтаблицы.

Пока я занимался этим, я переместил вложение postmeta и мета всех других типов записей в свои собственные таблицы.

Затем я подключился к get_(post_type)_metaфильтру, чтобы переопределить получение метаданных для обслуживания их из новых пользовательских таблиц.

Теперь тот же запрос, что и раньше, для получения которого потребовалось ~ 3 секунды, wp_postmetaзанимает ~ 0,006 секунды. Сайт теперь ведет себя так, как будто это была свежая установка WP.

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

Естественно, делать вещи в Wordpress лучше. Это на самом деле норма.

Однако также очевидно, что таблица EAV очень неэффективна при масштабировании. Он бесконечно гибок и позволяет хранить любые данные, но цена, которую вы платите за это, - это производительность. Это фундаментальный компромисс.

В этом контексте трудно сказать кому-то, кто намеревается иметь кучу тонны данных и - не дай бог - запрос / поиск по этим данным, чтобы wp_postmetaнаверняка использовать таблицу. Хит производительности будет отличным.

Использование пользовательских таблиц позволит накапливать ваши данные и при этом оставаться достаточно быстрым.

Так же, как Пиппин Уильямс, создатель плагина Easy Digital Downloads, упомянул, что будет использовать пользовательские таблицы, если он только начинает кодировать свой плагин, если вы собираетесь создать что-то, что будет использоваться в течение длительного времени или накапливать много данных, более эффективно использовать пользовательские таблицы, если вы хорошо их спроектируете.

Вы должны убедиться, что любой другой разработчик плагинов / надстроек имеет возможность подключиться к вашему плагину для манипулирования вашими данными до и после извлечения данных. Если вы это сделаете, то вы довольно солидны.

unity100
источник
1
Интересные вещи! Следует уточнить, что упомянутый фильтр «get_ (post_type) _meta» на самом деле называется «get_ (meta-type) _metadata»), где мета-тип - это либо запись, комментарий или пользователь. Таким образом, get_post_meta () будет проходить через фильтр get_post_metadata, независимо от типа записи. Возвращаемое значение фильтра - это то, что вы хотите, чтобы конечное мета-значение было.
Беренд
get_ (meta-type) _metadata -> действительно, он работает со всеми типами записей, и, действительно, последняя функция, которую посещают - get_post_metadata. Однако фильтр работает, когда вы используете его, тем не менее.
unity100
2

Это зависит от того, что вы делаете. Способ WP заключается в использовании существующих таблиц, так как они были разработаны так, чтобы быть достаточно гибкими, однако иногда вы получаете новый класс данных, которые нельзя разместить в существующей таблице, например, если вам нужны метаданные категории. Вы можете создать таблицу wp_termsmeta.

Однако, как правило, вы можете довольно удобно хранить ваши данные в разных существующих таблицах, и от того, где вы храните свои данные, зависит то, что делает ваш плагин.

  • Для общих настроек плагина используйте API-вызов get_option () - он также будет кэширован.
  • Для настроек плагина, относящихся к конкретному сообщению, используйте пользовательские метаданные для каждого сообщения с помощью get_post_meta () . Обычно этого достаточно для того, что вам нужно.

Кэширование реализовано в WordPress, чтобы ускорить ваше время отклика.

Дэн Смарт
источник
1

согласился с Денисом 100%. Но есть способ обойти это.

Проблема с использованием post meta для значений, которые должны быть запрошены, заключается в том, когда значения являются массивами и т. Д. Например:

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

Это сохраняется в БД в виде сериализованной строки, которая будет выглядеть примерно так:

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

Поэтому, когда вы хотите запросить все сообщения с помощью array['key2'] = 'val 2'wp, нужно извлечь каждую мета-запись, называемую массивом, распаковать ее, затем протестировать и перейти к следующему. Это определенно сломает ваш сервер, если ваш сайт успешен и имеет много постов, страниц, пользовательских постов и т. Д.

Решение зависит от проекта, и вы поймете, почему. Если вы будете хранить данные как var = valпотом, то wp сможет искать без php для распаковки каждого теста. Чтобы сделать это в приведенном выше сценарии, вы должны использовать пространство имен и сохранить мета-ключи:

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

тогда wp, ищущий ключ 2 с val 2, сможет сразу же вытащить его. Это зависит от проекта. Мой текущий проект опирается на около 20 различных типов данных, которые будут храниться с каждым настраиваемым сообщением, поэтому вышеприведенное просто создаст массивную таблицу для поиска, которая показывает, как мы ожидаем сотни тысяч сообщений. Таким образом, в этом сценарии пользовательская таблица является единственным способом.

Надеюсь, это поможет кому-то

Dáithí
источник
0

Для моего сайта FarmVille :) Я сделал оба, но так и не закончил, потому что продал это:

  1. Я прочитал Farmville XML и сбросил данные в пользовательскую таблицу
  2. В WordPress у меня были настраиваемые поля, автоматически создаваемые для каждого поля в этой таблице (и некоторые дополнительные)
  3. Теперь позаботьтесь о том, что произойдет, если значение изменится либо в таблице, либо на другой стороне: настраиваемое поле, поскольку они должны быть постоянно синхронизированы

Я сделал это, потому что я хотел, чтобы, с одной стороны, пользователи могли редактировать сайт WordPress, вводя новые данные Farmville, например, «корова стоит 10 монет», НО со стороны интеграции: ЕСЛИ изменение в XML корова теперь стоит «20 монет» (через плагин редактирования внешнего интерфейса), который будет задан как опция после него: так что либо XML, либо пользователь был прав (что-то вроде вики-системы).

Вот пример использования обоих.

edelwater
источник