2016-06-21 4 views
3

Я обновляю несколько строк в таблице. Выполнение запроса занимает много времени. Как повысить эффективность выполнения ниже запроса?Как повысить производительность запроса mysql?

update org_products op 
inner join access_history 
    on access_history.access_key = op.id and access_history.access_type = "OrgProduct.View" 
set views = 
(
    select count(access_key) 
    from access_history 
    where access_history.access_key = op.id and 
      access_history.created_at >= DATE_SUB(CURDATE(), INTERVAL 90 DAY) and 
      access_history.access_type = "OrgProduct.View" and 
      access_history.product_id = op.product_id 
    GROUP BY access_history.product_id 
) 
where access_history.access_key = op.id and 
     access_history.access_type = "OrgProduct.View"; 

Обновление: Выход SHOW CREATE TABLE access_history;

'access_history', 'CREATE TABLE `access_history` (
\n `id` bigint(20) NOT NULL AUTO_INCREMENT, 
\n `product_id` bigint(20) unsigned NOT NULL, 
\n `access_type` varchar(50) DEFAULT NULL, 
\n `access_key` varchar(50) DEFAULT NULL, 
\n `access_key_full` varchar(200) DEFAULT NULL, 
\n `client_ip_addr` varbinary(16) DEFAULT NULL, 
\n `userid` bigint(20) unsigned DEFAULT NULL,\n `username` tinytext, 
\n `anon_user_id` bigint(20) unsigned DEFAULT NULL, 
\n `created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, 
\n `updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,\n PRIMARY KEY (`id`), 
\n KEY `fk_access_history_has_product_product1_idx` (`product_id`), 
\n KEY `idx_access_history_prod_type_key` (`product_id`,`access_type`,`access_key`), 
\n CONSTRAINT `fk_access_history_has_product_product1_idx` FOREIGN KEY (`product_id`) REFERENCES `products` (`id`) ON 
DELETE NO ACTION ON UPDATE NO ACTION\n) ENGINE=InnoDB AUTO_INCREMENT=1290353 DEFAULT CHARSET=utf8' 

Выход из SHOW INDEX from access_history; enter image description here

Выход EXPLAIN query enter image description here

Какие изменения в запросе необходимы для повышения производительности?

Цените любую помощь! Благодаря!

+0

Ваше соединение и внешнее, если условия идентичны. Сначала я должен удалить второе условие из предложения join и первое условие из предложения where. –

+0

В предложении 'WHERE' есть некоторые повторяющиеся критерии. Не уверен, что это необходимо в вашем случае. Было бы неплохо, если бы вы могли предоставить образцы данных. – ydoow

+0

@TimBiegeleisen: Спасибо за немедленный ответ! Я попробовал то, что вы предложили, но результат все тот же. –

ответ

1

Есть 2 варианта здесь:

1) выполняемый обсуждаемый запрос периодически CRON - так что вы хотите, чтобы обновить все изделия, в которых доступ к истории была изменена в течение последних 90 дней. Попробуйте выполнить следующий запрос (вы должны заранее вычислить начальную дату, а затем использовать это постоянное значение - с помощью DATE_SUB() MySQL будет думать, что это динамическое значение и будет каждый раз вычислять его, не заметите, что это существенно константа):

UPDATE org_products op 
    SET views = (SELECT COUNT(*) FROM access_history 
     WHERE access_key = op.id 
      AND access_type = "OrgProduct.View" 
    ) 
    WHERE op.id IN (SELECT access_key FROM access_history 
     WHERE access_type = "OrgProduct.View" 
      AND created_at >= "YYYY-MM-DD" 
    ) 

2) вы выполняете обсуждаемый запрос после каждой вставки в таблицу access_history - попробуйте следующее (ACCESS_KEY_VALUE является то, что вы только что вставили в таблицу access_history):

UPDATE org_products op 
    SET views = (SELECT COUNT(*) FROM access_history 
     WHERE access_key = ACCESS_KEY_VALUE 
      AND access_type = "OrgProduct.View" 
    ) 
    WHERE op.id = ACCESS_KEY_VALUE 

В обоих случаях I рекомендуем переместить все отдельные строки из столбца access_type в отдельную таблицу, преобразовать столбец в INT и сделать его внешним ключом в эту новую таблицу. Причина в том, что индексирование и сравнение числовых значений быстрее, чем сравнение строк.

Смежные вопросы