Вот описание каждого из них, за которым следует образец реального мира.
API
. Пример : Если вы тестируете метод класса, который требует много обязательных параметров в конструкторе, который не имеет эффекта в вашем тесте, тогда вы можете создать фиктивные объекты для цель создания новых экземпляров класса. in-memory
. state-based
. Пример : ваш тестовый класс зависит от метода Calculate()
, который занимает 5 минут. Вместо того, чтобы ждать 5 минут, вы можете заменить его реальную реализацию заглушкой, которая возвращает жестко заданные значения; занимая лишь небольшую часть времени. Stub
, но interaction-based
, а не на состояние. Это означает, что вы не ожидаете, что Mock
вернет некоторое значение, но предположим, что выполняется конкретный порядок вызовов методов. Пример. Вы тестируете класс регистрации пользователя. После вызова Save
он должен вызвать SendConfirmationEmail
. Stubs
и Mocks
на самом деле являются подтипами Mock
, и реальная реализация swap с тестовой реализацией, но по разным конкретным причинам.
Первое, что нужно сделать, это проверить, есть ли у вас правильные индексы во всех столбцах, где вы ВСТРЕТИЛИСЬ и где вы фильтруете. Обычно отсутствие индексов является причиной медленных запросов.
Если вы хотите пойти дальше, я бы перестроил индексы. Возможно, некоторая фрагментация также замедляет процесс.
Хотя это и не обязательно, вы также можете попробовать перенести ключи, такие как wc-complete, wc-processing, в свою собственную таблицу и выполнить соединения с помощью INT.
Вы также можете попытаться нормализовать SUM или даже создать вычисляемый столбец для них.
meta_key
-предикаты в JOIN
с Я позволил себе отформатировать ваш запрос для ясности.
Я переименовал псевдонимы и переместил meta_key
-предикаты из WHERE
в JOIN
с:
SELECT
(SELECT meta_value
FROM `myprefix_postmeta` as postmeta
WHERE
postmeta.meta_key = '_sku'
AND postmeta.post_id = IM3.meta_value ) AS sku,
I.order_item_name AS title,
SUM (IM.meta_value ) AS quantity,
SUM (IM2.meta_value ) AS total
FROM
`myprefix_woocommerce_order_items` AS I
LEFT JOIN `myprefix_posts` AS posts
ON posts.ID = I.order_id
LEFT JOIN `myprefix_woocommerce_order_itemmeta` AS IM -- Make readable aliases
ON IM.order_item_id = I.order_item_id
AND IM.meta_key = '_qty' -- Move predicates from WHERE
LEFT JOIN `myprefix_woocommerce_order_itemmeta` AS IM2
ON IM2.order_item_id = I.order_item_id
AND IM2.meta_key = '_line_total' -- Move predicates from WHERE
LEFT JOIN `myprefix_woocommerce_order_itemmeta` AS IM3
ON IM3.order_item_id = I.order_item_id
AND IM3.meta_key = '_product_id' -- Move predicates from WHERE
WHERE
posts.post_type = 'shop_order'
AND posts.post_status IN
( 'wc-completed', 'wc-processing', 'wc-on-hold' )
GROUP BY
IM3.meta_value
ORDER BY
total DESC
Теперь у нас есть абсолютно эквивалентный запрос.
Давайте посмотрим, что мы можем сделать дальше.
LEFT JOIN
с myprefix_woocommerce_order_itemmeta
с тем же предикатом IM.order_item_id = I.order_item_id
выглядит ненужным дублированием meta_key
Таким образом, мы можем:
a. Замените 3 СОЕДИНЕНИЯ только одним СОЕДИНЕНИЕМ
b. Замените поля IM / IM2 / IM3 CASE-выражениями
SELECT
(SELECT meta_value
FROM `myprefix_postmeta` as postmeta
WHERE
postmeta.meta_key = '_sku'
AND postmeta.post_id = ( -- Substitute meta_value with CASE-expressions
CASE
WHEN IM.meta_key = '_product_id' THEN IM.meta_value
ELSE NULL
END
) -- IM3.meta_value
) AS sku,
I.order_item_name AS title,
SUM (
CASE -- Substitute meta_value with CASE-expressions
WHEN IM.meta_key = '_qty' THEN IM.meta_value
ELSE 0
END
) AS quantity
-- IM2.meta_value ) AS total
SUM ( -- Substitute meta_value with CASE-expressions
CASE
WHEN IM.meta_key = '_line_total' THEN IM.meta_value
ELSE 0
END
) AS total
FROM
`myprefix_woocommerce_order_items` AS I
LEFT JOIN `myprefix_posts` AS posts
ON posts.ID = I.order_id
LEFT JOIN `myprefix_woocommerce_order_itemmeta` AS IM -- Make readable aliases
ON IM.order_item_id = I.order_item_id
AND IM.meta_key IN ('_qty', '_line_total', '_product_id')
-- AND IM.meta_key = '_qty' -- Move predicates from WHERE
-- LEFT JOIN `myprefix_woocommerce_order_itemmeta` AS IM2
-- ON IM2.order_item_id = I.order_item_id
-- AND IM2.meta_key = '_line_total' -- Move predicates from WHERE
-- LEFT JOIN `myprefix_woocommerce_order_itemmeta` AS IM3
-- ON IM3.order_item_id = I.order_item_id
-- AND IM3.meta_key = '_product_id' -- Move predicates from WHERE
WHERE
posts.post_type = 'shop_order'
AND posts.post_status IN
( 'wc-completed', 'wc-processing', 'wc-on-hold' )
GROUP BY
(
CASE
WHEN IM.meta_key = '_product_id' THEN IM.meta_value
ELSE NULL
END
) -- IM3.meta_value
ORDER BY
total DESC
Не очень удобно писать SQL без данных.
И возможно, что этот запрос некорректен для каждой версии mysql.
Поэтому постарайтесь понять принципы, а не просто скопировать и вставить мой код.
Сообщите нам о результатах или проблемах.
Если woocommerce является ответвлением WordPress, то они, вероятно, плохо справились с индексацией myprefix_woocommerce_order_itemmeta
. Адаптировать подсказки в здесь для улучшения производительности.
Я согласен с другими - шаблон схемы EAV - отстой. Мои предложения по указателю выше помогают , некоторые .
Например, и «order» всегда имеет qty, product_id, line_total; так почему бы не использовать их как настоящие столбцы, если они скрыты в другой таблице, как если бы они были редкими атрибутами? EAV в некоторой степени необходим для магазина, где только некоторые предметы имеют «размер платья», «F-стоп» или «тип передачи». (В этом случае JSON может быть лучшим шаблоном, чем EAV.)
Обзор схемы
Фу, woocommerce хуже чем WP ([ 114] ссылка ):
CREATE TABLE {$wpdb->prefix}woocommerce_order_itemmeta (
meta_id BIGINT UNSIGNED NOT NULL auto_increment,
order_item_id BIGINT UNSIGNED NOT NULL,
meta_key varchar(255) default NULL,
meta_value longtext NULL,
PRIMARY KEY (meta_id),
KEY order_item_id (order_item_id),
KEY meta_key (meta_key(32))
) $collate;
Индексирование префиксов (meta_key(32)
) редко используется и часто приводит к обратным результатам. Тем не менее, вероятно, все мои рекомендации (см. Ссылку выше) применимы, с подходящими изменениями имени.