Задать вопрос

Влияние типа поля на быстродействие индекса. MySQL?

Есть таблица:

CREATE TABLE `articles` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `content` text NOT NULL,
  `url` text NOT NULL,
  `status` enum('edit','order','place', 'user') DEFAULT 'edit',
  PRIMARY KEY (`id`),
  KEY `ix__status` (`status`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
/*!50100 PARTITION BY RANGE (id)
(PARTITION articles_p1 VALUES LESS THAN (50000) ENGINE = InnoDB,
 PARTITION articles_p2 VALUES LESS THAN (100000) ENGINE = InnoDB,
 PARTITION articles_p3 VALUES LESS THAN (150000) ENGINE = InnoDB,
 PARTITION articles_p4 VALUES LESS THAN (200000) ENGINE = InnoDB,
 PARTITION articles_p5 VALUES LESS THAN (250000) ENGINE = InnoDB,
 PARTITION articles_p6 VALUES LESS THAN (300000) ENGINE = InnoDB,
 PARTITION articles_p7 VALUES LESS THAN (350000) ENGINE = InnoDB,
 PARTITION articles_p8 VALUES LESS THAN (400000) ENGINE = InnoDB,
 PARTITION articles_p9 VALUES LESS THAN (450000) ENGINE = InnoDB,
 PARTITION articles_p10 VALUES LESS THAN (500000) ENGINE = InnoDB,
 PARTITION articles_p11 VALUES LESS THAN MAXVALUE ENGINE = InnoDB) */



Таблица очень жирная, общий объем >10Gb. В ходе тестов тип поля url был заменен на varchar(8000). После этого запросы типа
SELECT COUNT(*) AS `count` FROM `articles`  WHERE `status` NOT IN ('edit', 'order');


стали выполняться очень медленно (около 8 сек). План выполнения:
'1', 'SIMPLE', 'Article', 'index', 'status', 'status', '2', NULL, '1229613', 'Using where; Using index'


Но в этих статусах ('edit', 'order') менее 1% всех записей, т.е. индекс в данном случае не эффективен, но, если вернуть тип поля опять на TEXT время выполнения этого же запроса уменьшается до 0.5 секунды.

План выполнения при этом не меняется.


В чем причина такого поведения innodb?
  • Вопрос задан
  • 4398 просмотров
Подписаться 9 Оценить 1 комментарий
Решения вопроса 1
@egorinsk
Подозреваю, дело в том, что VARCHAR и TEXT данные хранятся разным способом:

> For BLOB and TEXT data, the information is stored internally in a different area of memory than the row buffer.

dev.mysql.com/doc/refman/5.0/en/storage-requirements.html
Ответ написан
Пригласить эксперта
Ответы на вопрос 4
@shagguboy
SET profiling = 1;
ваш запрос
SHOW PROFILES;
сделать для обоих вариантов таблицы, выложить сюда.
Ответ написан
Melkij
@Melkij
PostgreSQL DBA
Но в этих статусах ('edit', 'order') менее 1% всех записей, т.е. индекс в данном случае не эффективен
Таки наоборот. Чем меньше записей от общей массы подпадает — тем эффективнее индекс.

Попробуйте с count(0), т.е. по константе. Есть мнение, что mysql вычитывает все подошедшие строки, а text'ы — не читает, т.к. расположены отдельно от таблицы.
Ответ написан
@TimTowdy
Покажите EXPLAIN запроса по таблице без VARCHAR(8000). Или попробуйте FORCE INDEX на этой таблице. Есть подозрение что индекс не используется, т.к. фулскан быстрее. Замена TEXT на VARCHAR(8000) замедляет фулскан и включается индекс, что и приводит к замедлению.
Ответ написан
@shagguboy
как успехи?
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы