2015-03-10 7 views
-1

У меня есть веб-сайт с двумя основными запросами к базе данных, которые довольно медленны при первом запуске, после небольшого тестирования, похоже, проблема с MySQL. Если я запускаю запрос непосредственно в Sequal Pro, когда я запускаю запрос, первый раз, когда он может занять до 4 секунд для запуска, но запуск того же запроса снова занимает ~ 60 мс, время запроса примерно такое же, как на нашем сервере, что заставьте меня думать, что это не проблема сервера.MySQL Long First Query Time

Не совсем уверен, что увеличение размера пула буферов поможет слишком много, так как количество возможных комбинаций запросов составляет около 800K.

Таблицы в базе данных являются innodb, оба запроса имеют доступ к одной и той же таблице, содержащей 52K записей, большая часть необходимой мне информации была сгруппирована в поле «searchfield», которое индексируется.

Индексируются только поля, используемые в запросах или первичные/внешние ключи.

Я попытался изменить внутренние соединения на оператор select в «где» основного запроса, но это не ускоряет запрос.

В запросы

Запрос 1

SELECT 
    `item_attribute`.`attribute_id` AS `attribute_id`, 
    `attribute_value_id` AS `attribute_value_id`, 
    `collection_attribute`.`title` AS `ca_title`, 
    `collection_attribute`.`type` AS `ca_type`, 
    `collection_attribute`.`is_collapsible` AS `ca_is_collapsible`, 
    `collection_attribute`.`orderindex` AS `ca_orderindex`, 
    `collection_attribute`.`multi_select` AS `ca_multi_select`, 
    `item_attribute`.`item_id` AS `item_id`, 
    `product`.`id` AS `product_id` 
    FROM `item_attribute` 
    INNER JOIN `item` ON item.id = item_attribute.item_id 
    INNER JOIN `product` ON product.id = item.product_id 
    INNER JOIN `collection_attribute` ON item_attribute.attribute_id = collection_attribute.attribute_id 
    INNER JOIN `attribute_value` ON attribute_value.id = item_attribute.attribute_value_id 
    WHERE ((`product`.`searchfilter` LIKE '%c:35∆%') AND (`collection_attribute`.`collection_id`='35')) AND (`attribute_value`.`active`=1) 
    GROUP BY `attribute_value_id` 

Запрос 2

SELECT DISTINCT `item_attribute`.`attribute_id` AS `attribute_id`, 
    GROUP_CONCAT(item_attribute.attribute_value_id SEPARATOR \"-\") AS `attribute_value`, 
    GROUP_CONCAT(attribute_value.title SEPARATOR \" - \") AS `title` 
    FROM `item_attribute` 
    LEFT JOIN `item` ON item.id = item_attribute.item_id 
    LEFT JOIN `attribute` ON attribute.id = item_attribute.attribute_id 
    LEFT JOIN `attribute_value` ON attribute_value.id = attribute_value_id 
    WHERE (`item`.`product_id`='894') AND (`attribute`.`is_option`=1) 
    GROUP BY `attribute_id`, `item_id` 

Структура таблицы

CREATE TABLE `product` (
    `id` int(11) NOT NULL AUTO_INCREMENT, 
    `title` varchar(255) NOT NULL, 
    `slug` varchar(255) NOT NULL, 
    `sku` varchar(20) NOT NULL, 
    `active` tinyint(1) DEFAULT '0', 
    `orderindex` int(2) DEFAULT '-1', 
    `search` varchar(255) DEFAULT NULL, 
    `searchfilter` varchar(255) DEFAULT NULL, 
    `created_at` int(11) DEFAULT NULL, 
    `updated_at` int(11) DEFAULT NULL, 
    `protected` tinyint(1) DEFAULT '0', 
    `description` varchar(512) DEFAULT NULL, 
    `type_id` int(11) DEFAULT NULL, 
    PRIMARY KEY (`id`), 
    KEY `product_ibfk_1` (`type_id`), 
    KEY `searchfilter` (`searchfilter`), 
    CONSTRAINT `product_ibfk_1` FOREIGN KEY (`type_id`) REFERENCES `attribute_value` (`id`) ON DELETE CASCADE ON UPDATE CASCADE 
) ENGINE=InnoDB AUTO_INCREMENT=1882 DEFAULT CHARSET=utf8; 

-

CREATE TABLE `collection_attribute` (
    `id` int(11) NOT NULL AUTO_INCREMENT, 
    `collection_id` int(11) DEFAULT NULL, 
    `attribute_id` int(11) DEFAULT NULL, 
    `title` varchar(512) NOT NULL, 
    `slug` varchar(512) NOT NULL, 
    `created_at` int(11) DEFAULT NULL, 
    `updated_at` int(11) DEFAULT NULL, 
    `active` tinyint(1) DEFAULT '0', 
    `orderindex` int(2) DEFAULT '-1', 
    `search` varchar(255) DEFAULT NULL, 
    `searchfilter` varchar(255) DEFAULT NULL, 
    `protected` tinyint(1) DEFAULT '0', 
    `is_collapsible` tinyint(1) DEFAULT '0', 
    `type` enum('icon','checkbox','checkboxIcon','image') DEFAULT NULL, 
    `multi_select` tinyint(1) DEFAULT '0', 
    PRIMARY KEY (`id`), 
    KEY `collection_attribute_ibfk_1` (`collection_id`), 
    KEY `collection_attribute_ibfk_2` (`attribute_id`), 
    CONSTRAINT `collection_attribute_ibfk_1` FOREIGN KEY (`collection_id`) REFERENCES `collection` (`id`) ON DELETE CASCADE ON UPDATE CASCADE, 
    CONSTRAINT `collection_attribute_ibfk_2` FOREIGN KEY (`attribute_id`) REFERENCES `attribute` (`id`) ON DELETE CASCADE ON UPDATE CASCADE 
) ENGINE=InnoDB AUTO_INCREMENT=140 DEFAULT CHARSET=utf8; 

-

CREATE TABLE `item` (
    `id` int(11) NOT NULL AUTO_INCREMENT, 
    `slug` varchar(255) NOT NULL, 
    `title` varchar(255) NOT NULL, 
    `pattern_code` varchar(32) NOT NULL, 
    `tom_code` varchar(32) NOT NULL, 
    `navision_code` varchar(32) NOT NULL, 
    `description` varchar(255) DEFAULT NULL, 
    `active` tinyint(1) DEFAULT '0', 
    `orderindex` int(2) DEFAULT '-1', 
    `created_at` int(11) DEFAULT NULL, 
    `updated_at` int(11) DEFAULT NULL, 
    `search` varchar(1024) DEFAULT NULL, 
    `searchfilter` varchar(255) DEFAULT NULL, 
    `product_id` int(11) DEFAULT NULL, 
    `protected` tinyint(1) DEFAULT '0', 
    `pattern_series` varchar(255) DEFAULT NULL, 
    `pattern_id` int(11) DEFAULT NULL, 
    PRIMARY KEY (`id`), 
    KEY `item_ibfk_1` (`product_id`), 
    KEY `searchfilter` (`searchfilter`), 
    KEY `product_id` (`product_id`), 
    KEY `pattern_id` (`pattern_id`), 
    CONSTRAINT `item_ibfk_1` FOREIGN KEY (`product_id`) REFERENCES `product` (`id`) ON DELETE CASCADE ON UPDATE CASCADE, 
    CONSTRAINT `item_ibfk_2` FOREIGN KEY (`pattern_id`) REFERENCES `pattern_series` (`id`) ON DELETE CASCADE ON UPDATE CASCADE 
) ENGINE=InnoDB AUTO_INCREMENT=50060 DEFAULT CHARSET=utf8; 

-

CREATE TABLE `item_attribute` (
    `id` int(11) NOT NULL AUTO_INCREMENT, 
    `item_id` int(11) NOT NULL, 
    `attribute_id` int(11) NOT NULL, 
    `attribute_value_id` int(11) NOT NULL, 
    PRIMARY KEY (`id`), 
    KEY `attribute_id` (`attribute_id`), 
    KEY `attribute_value_id` (`attribute_value_id`), 
    KEY `item_id` (`item_id`), 
    CONSTRAINT `item_attribute_ibfk_1` FOREIGN KEY (`attribute_id`) REFERENCES `attribute` (`id`) ON DELETE CASCADE ON UPDATE CASCADE, 
    CONSTRAINT `item_attribute_ibfk_2` FOREIGN KEY (`attribute_value_id`) REFERENCES `attribute_value` (`id`) ON DELETE CASCADE ON UPDATE CASCADE, 
    CONSTRAINT `item_attribute_ibfk_3` FOREIGN KEY (`item_id`) REFERENCES `item` (`id`) ON DELETE CASCADE ON UPDATE CASCADE 
) ENGINE=InnoDB AUTO_INCREMENT=857111 DEFAULT CHARSET=utf8; 

-

CREATE TABLE `attribute_value` (
    `id` int(11) NOT NULL AUTO_INCREMENT, 
    `slug` varchar(255) NOT NULL, 
    `code` varchar(255) DEFAULT NULL, 
    `title` varchar(255) NOT NULL, 
    `active` tinyint(1) DEFAULT '0', 
    `orderindex` int(2) DEFAULT '-1', 
    `created_at` int(11) DEFAULT NULL, 
    `updated_at` int(11) DEFAULT NULL, 
    `search` varchar(255) DEFAULT NULL, 
    `searchfilter` varchar(255) DEFAULT NULL, 
    `attribute_id` int(11) DEFAULT NULL, 
    `protected` tinyint(1) DEFAULT '0', 
    PRIMARY KEY (`id`) 
) ENGINE=InnoDB AUTO_INCREMENT=3471 DEFAULT CHARSET=utf8; 

-

CREATE TABLE `attribute` (
    `id` int(11) NOT NULL AUTO_INCREMENT, 
    `title` varchar(255) NOT NULL, 
    `slug` varchar(255) NOT NULL, 
    `code` varchar(255) DEFAULT NULL, 
    `is_option` tinyint(1) DEFAULT '0', 
    `searches` tinyint(1) DEFAULT '0', 
    `option_type` enum('dropdown','switch','fingersizes') DEFAULT NULL, 
    `option_label` varchar(32) DEFAULT NULL, 
    `active` tinyint(1) DEFAULT '0', 
    `orderindex` int(2) DEFAULT '-1', 
    `created_at` int(11) DEFAULT NULL, 
    `updated_at` int(11) DEFAULT NULL, 
    `search` varchar(255) DEFAULT NULL, 
    `searchfilter` varchar(255) DEFAULT NULL, 
    `protected` tinyint(1) DEFAULT '0', 
    `option_requires` int(11) DEFAULT NULL, 
    `option_depends` int(11) DEFAULT NULL, 
    PRIMARY KEY (`id`), 
    KEY `is_option` (`is_option`) 
) ENGINE=InnoDB AUTO_INCREMENT=47 DEFAULT CHARSET=utf8; 

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

Заранее спасибо :)

- EDIT -

EXPLAIN SELECT запрос 1 Explain Select

EXPLAIN SELECT запрос, 2 Explain select

ответ

2

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

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

innodb_buffer_pool_size должно составлять около 70% доступной оперативной памяти. Изменение значения не повлияет на SELECT для холодного кеша, но может помочь/повредить последующие прогоны. Это не похоже на ваш случай, так как второй прогон был довольно быстрым.

Пожалуйста, предоставьте EXPLAIN SELECT ..., чтобы мы могли увидеть, как оптимизатор решил их выполнить.

LIKE '%c:35∆%' - Нельзя использовать индекс из-за ведущей дикой карты.

Что такое item_ids?

item_attribute - схема схемы EAV. Это отстой. Оба запроса уродливы, а масштабируемость болит. Это может помочь примерно, чтобы избавиться от id и сделать составной PRIMARY KEY из подходящей комбинации других полей. Надеемся использовать PRIMARY KEY, который кластеризуется с данными вместо того, чтобы отскакивать от вторичного ключа. More discussion of EAV.

Предполагая, что это имеет низкую мощность, не будет, вероятно, будет использоваться индекс никогда:
KEY is_option (is_option)

+0

спасибо за информацию. Я попробую изменить подстановочный знак на другое соединение и посмотреть, поможет ли это кому-либо. и спасибо за информацию о EAV, посмотрим, смогу ли я заставить ее работать с Yii :) Прокомментировал техническую поддержку нашего сервера, и он рекомендовал изменить размер пула до 40%, хотя я видел в другом сообщении на здесь он может идти до 70%, но это только кажется, что он содержит 3 запроса 1. У нас есть 1 ГБ ОЗУ, поэтому размер пула в настоящее время составляет около 400 МБ. –

+0

Ouch. 1GB. Даже 400 МБ опасно высока. Подкачка _very_ плохо для производительности MySQL, хуже, чем наличие buffer_pool. Проверьте остальную часть my.cnf - несколько других вещей, возможно, нуждаются в понижении. –

+0

Умм, но вы сказали: «innodb_buffer_pool_size должно быть около 70% доступной ОЗУ», его значение установлено только на 40%, и теперь ваше высказывание слишком велико. Я немного смущен относительно того, к чему это теперь нужно установить, изначально было только 48 МБ –