Форум: Форум PHPФорум ApacheФорум Регулярные ВыраженияФорум MySQLHTML+CSS+JavaScriptФорум FlashРазное
Новые темы: 0000000
PHP Puzzles. Авторы: Кузнецов М.В., Симдянов И.В. Программирование. Ступени успешной карьеры. Авторы: Кузнецов М.В., Симдянов И.В. MySQL 5. В подлиннике. Авторы: Кузнецов М.В., Симдянов И.В. PHP на примерах (2 издание). Авторы: Кузнецов М.В., Симдянов И.В. PHP 5/6. В подлиннике. Авторы: Кузнецов М.В., Симдянов И.В.
ВСЕ НАШИ КНИГИ
Консультационный центр SoftTime

Форум MySQL

Выбрать другой форум

 

Здравствуйте, Посетитель!

вид форума:
Линейный форум Структурный форум

тема: Оптимизация запросов с помощью индексов
 
 автор: daniel20   (12.12.2011 в 19:43)   письмо автору
 
 

Здравствуйте!
имею 2 таблицы:

CREATE TABLE items(
  items_id INT(11) NOT NULL AUTO_INCREMENT,
  name VARCHAR(255) DEFAULT NULL,
  when_added TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP,
  items_manufacturers_id VARCHAR(255) DEFAULT NULL,
  items_images_id INT(11) UNSIGNED DEFAULT NULL,
  classifier_id INT(11) DEFAULT NULL,
  PRIMARY KEY (items_id),
  INDEX IX_items_classifier_id (classifier_id)
)
ENGINE = INNODB
AUTO_INCREMENT = 104035
AVG_ROW_LENGTH = 68
CHARACTER SET utf8
COLLATE utf8_general_ci;


как видно, индексирована колонка items_id (уникальный ключь)
и вторая таблица:


CREATE TABLE items_prices(
  items_prices_id INT(11) NOT NULL AUTO_INCREMENT,
  online_stores_items_id INT(11) DEFAULT NULL,
  new_price DECIMAL(10, 2) DEFAULT NULL,
  available SMALLINT(1) UNSIGNED DEFAULT NULL,
  when_added TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  old_price VARCHAR(100) DEFAULT NULL,
  description TEXT DEFAULT NULL,
  contact_phones TINYTEXT DEFAULT NULL,
  currency TINYINT(4) DEFAULT 1
  is_current_price BIT(1) DEFAULT b'1',
  items_id INT(11) DEFAULT NULL,
  PRIMARY KEY (items_prices_id),
  INDEX IX_items_prices (items_id)
)
ENGINE = INNODB
AUTO_INCREMENT = 66076
AVG_ROW_LENGTH = 61
CHARACTER SET utf8
COLLATE utf8_general_ci;


как видно, индексирована колонка items_id (не уникальный ключь)

в общем вот какая проблема: при простой связки этих таблиц по items_id запрос становится тяжелее и за ежедневного роста не уникальных индексов items_id таблицы items_prices. Как можно этого избежать?
!!! Проблема именно в не уникальных индексов потому что с другими таблицами связка идет на ура.

  Ответить  
 
 автор: cheops   (12.12.2011 в 20:26)   письмо автору
 
   для: daniel20   (12.12.2011 в 19:43)
 

1. А можно еще EXPLAIN-схему запроса увидеть?
2. InnoDB специально используете? Можно услышать причины? Или вам все-равно, если да, то переведите лучше в MyISAM - там индексы отдельные, а в InnoDB они физические, причем первым идет первичный ключ, у вас ведь по сути не два отдельных ключа, как вам, возможно кажется, у вас один ключ по двум столбцам. InnoDB - это такой очень странный тип таблицы, её бы хорошо саму знать, чтобы с ней работать и базу данных под неё желательно целиком настраивать (так чтобы там вообще MyISAM таблиц практически не было).

PS Если лень/не интересно, на второй вопрос можно не отвечать :)))

  Ответить  
 
 автор: daniel20   (13.12.2011 в 11:56)   письмо автору
 
   для: cheops   (12.12.2011 в 20:26)
 

1    SIMPLE    ip    index    (null)    IX_prc_items_prices    18    (null)    60203    Using where; Using index; Using temporary; Using filesort
1    SIMPLE    i    eq_ref    PRIMARY    PRIMARY    4    price.ip.items_id    1    Using index


На счет INNODB - мой шеф приказал везде использовать транзакции. С ним не поспоришь.

  Ответить  
 
 автор: cheops   (13.12.2011 в 13:43)   письмо автору
 
   для: daniel20   (13.12.2011 в 11:56)
 

Вот смотрите что происходит, в случае IX_prc_items_prices - происходит полный скан таблицы (60203 строки), причем таблица сбрасывается на диск, сортировка будет обычная без использования индекса, в случае price.ip.items_id - все отлично, данные даже не затрагиваются в этом запросе, MySQL обходится индексами.

  Ответить  
 
 автор: daniel20   (13.12.2011 в 15:07)   письмо автору
 
   для: cheops   (13.12.2011 в 13:43)
 

Блин. Но как сделать сортировку быстрой? вот запрос:
SELECT 
     `i`.`items_id`
     , `ip`.`new_price`
FROM
  items i
INNER JOIN `items_prices` AS `ip`
ON i.items_id = ip.items_id AND is_current_price = 1
GROUP BY
  `ip`.`items_id`
ORDER BY
  `ip`.`new_price` ASC
LIMIT
  4


пробовал создать индекс: `ip`.`items_id`,`ip`.`new_price`. Ничего не дает.

  Ответить  
 
 автор: cheops   (13.12.2011 в 15:36)   письмо автору
 
   для: daniel20   (13.12.2011 в 15:07)
 

Попробуйте для начала так (только скорости реально замеряйте - стало быстрее или медленее)
SELECT  
     `i`.`items_id` 
     , `ip`.`new_price` 
FROM 
  items i 
INNER JOIN
 (SELECT * FROM `items_prices`
  WHERE is_current_price = 1) AS `ip` 
ON i.items_id = ip.items_id
GROUP BY 
  `ip`.`items_id` 
ORDER BY 
  `ip`.`new_price` ASC 
LIMIT 
  4

  Ответить  
 
 автор: daniel20   (13.12.2011 в 16:33)   письмо автору
 
   для: cheops   (13.12.2011 в 15:36)
 

запуск 3 раза моего запроса: 0.177, 0.177, 0.178
запуск 3 раза вашего запроса: 0.600, 0.618, 0.612

немножко оптимизировал ваш запрос (поменял * на items_id, new_price)
запуск 3 раза данного запроса: 0.179, 0.191, 0.186

Еще забыл сказать, поменял эти две таблицы с InnoDB на MyIsam. Запустил этот запрос, работает медленее. Наверно Mysql settings не оптимизировал под MyIsam, а то ничего другого не приходит в голову. Ожидал более обыстрой работы.

  Ответить  
 
 автор: cheops   (13.12.2011 в 17:52)   письмо автору
 
   для: daniel20   (13.12.2011 в 16:33)
 

>Еще забыл сказать, поменял эти две таблицы с InnoDB на MyIsam. Запустил этот запрос,
>работает медленнее. Наверно Mysql settings не оптимизировал под MyIsam, а то ничего другого не
>приходит в голову. Ожидал более обыстрой работы.
Если сервер под InnoDB заточен, MyISAM и не будет быстро работать, у этого типа таблиц скорее всего все отрезано и отдано InnoDB. Насколько я понял, ответ на второй вопрос, перефразируя вашего шефа "ничего не трогайте, все под InnoDB сконфигурировано".

  Ответить  
 
 автор: cheops   (13.12.2011 в 17:53)   письмо автору
 
   для: daniel20   (13.12.2011 в 16:33)
 

Повесьте индекс на is_current_price - меняется ли скорость запроса? После этого, если не сложно приведите EXPLAIN - сколько записей перелопачивается во внутреннем запросе?

  Ответить  
 
 автор: daniel20   (13.12.2011 в 18:52)   письмо автору
 
   для: cheops   (13.12.2011 в 17:53)
 

Вооо, что делает уставшая голова: смотро, индексы уже стояли IX_prc_items_prices(items_id, is_current_price, new_price) запускаю: 0.17 мин. Думаю давай создам индексы по отдельности (выше группа идет) старый индекс удалил и создал по отдельности. Выполняю: 0.2сек. - это логично. Удаляю эти и делаю все как было. Выполняю: 0.058сек. Как так? сам не понял. Пора домой пойти.....

  Ответить  
 
 автор: cheops   (13.12.2011 в 19:17)   письмо автору
 
   для: daniel20   (13.12.2011 в 18:52)
 

Хм... судя по всему таблички время от времени чинить/проверять нужно... ну или так вот (удалить, снова создать).

  Ответить  
Rambler's Top100
вверх

Rambler's Top100 Яндекс.Метрика Яндекс цитирования