![]()  | 
		
Задавайте вопросы, мы ответим
Вы не зашли.
Здравствуйте.
Есть вот такая табличка:
mysql> DESCRIBE `friends_history`;
+------------+----------------------+------+-----+-------------------+-----------------------------+
| Field | Type | Null | Key | Default | Extra |
+------------+----------------------+------+-----+-------------------+-----------------------------+
| _id | int(11) unsigned | NO | PRI | NULL | auto_increment |
| user_id | int(11) unsigned | NO | PRI | NULL | |
| type | enum('remove','add') | NO | | NULL | |
| users_list | mediumtext | NO | | NULL | |
| date | timestamp | NO | MUL | CURRENT_TIMESTAMP | on update CURRENT_TIMESTAMP |
+------------+----------------------+------+-----+-------------------+-----------------------------+
mysql> SHOW INDEXES FROM `friends_history`;
+-----------------+------------+--------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+-----------------+------------+--------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| friends_history | 0 | PRIMARY | 1 | _id | A | 49470030 | NULL | NULL | | BTREE | | |
| friends_history | 0 | PRIMARY | 2 | user_id | A | 49470030 | NULL | NULL | | BTREE | | |
| friends_history | 1 | date | 1 | date | A | 49470030 | NULL | NULL | | BTREE | | |
| friends_history | 1 | user_id+date | 1 | user_id | A | 2748335 | NULL | NULL | | BTREE | | |
| friends_history | 1 | user_id+date | 2 | date | A | 49470030 | NULL | NULL | | BTREE | | |
+-----------------+------------+--------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
И вот такой к ней запрос:
mysql> EXPLAIN SELECT `type`,`users_list` FROM `friends_history` WHERE `user_id` = 1052662 ORDER BY `date` DESC;
+----+-------------+-----------------+------+---------------+--------------+---------+-------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-----------------+------+---------------+--------------+---------+-------+------+-------------+
| 1 | SIMPLE | friends_history | ref | user_id+date | user_id+date | 4 | const | 33 | Using where |
+----+-------------+-----------------+------+---------------+--------------+---------+-------+------+-------------+
Объясните, пожалуйста, из-за чего здесь USING WHERE? Можно ли его побороть?
Второй вопрос состоит в том, что запрос без сортировки исправно выдаёт отсортированный по date результат (date в нашем случае - дата добавления записи). Можно ли полагаться на это? Ведь по идеи mysql не обязан этого делать.
mysql> EXPLAIN SELECT `type`,`users_list` FROM `friends_history` WHERE `user_id` = 1052662;
+----+-------------+-----------------+------+---------------+--------------+---------+-------+------+-------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-----------------+------+---------------+--------------+---------+-------+------+-------+
| 1 | SIMPLE | friends_history | ref | user_id+date | user_id+date | 4 | const | 33 | |
+----+-------------+-----------------+------+---------------+--------------+---------+-------+------+-------+
Спасибо.)
Неактивен

На колонке, которая поддерживает NULL, — нельзя. NULLы то отсеивать надо 
как-то ![]()
Полагаться не стоит, так как это не документированная особенность MyISAM.
Например, удаление строки, а потом добавление новой, вставит строку физи-
чески не в конец таблицы, а в освободившееся место, и недокументированная
сортировка нарушится. Ну и если будете переходить на InnoDB, сможете это
сделать куда проще, если не будете использовать такие особенности ![]()
Неактивен
Эм...)
Так никакая из колонок NULL и не поддерживает.
И это уже InnoDB.
mysql-5.5.8
Может так понятнее
CREATE TABLE `friends_history` (
`_id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`user_id` int(11) unsigned NOT NULL,
`type` enum('remove','add') NOT NULL COMMENT '1-add; 0-remove;',
`users_list` mediumtext NOT NULL,
`date` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`_id`,`user_id`),
KEY `date` (`date`),
KEY `user_id+date` (`user_id`,`date`)
) ENGINE=InnoDB AUTO_INCREMENT=47224987 DEFAULT CHARSET=utf8
Отредактированно rs7 (30.01.2011 12:29:48)
Неактивен

Да, так куда понятнее, а то смотрел на DEFAULT NULL ![]()
В InnoDB строки сортируются по PRIMARY KEY всегда, на это можно полагаться.
Соответственно, если _id у Вас растет честным автоинкрементом, то он будет
расти с датой в том числе 
 Кстати, а зачем там user_id в PK?
Что касается Using where в данном случае — смотрите последний комментарий
Тобиаса в http://bugs.mysql.com/bug.php?id=30733 . Впрочем, насколько я пони-
маю, это проблема отображения, а не выполнения запроса.
Неактивен
paulus написал:
В InnoDB строки сортируются по PRIMARY KEY всегда, на это можно полагаться.
Соответственно, если _id у Вас растет честным автоинкрементом, то он будет
расти с датой в том числе
Кстати, а зачем там user_id в PK?
Что касается Using where в данном случае — смотрите последний комментарий
Тобиаса в http://bugs.mysql.com/bug.php?id=30733 . Впрочем, насколько я пони-
маю, это проблема отображения, а не выполнения запроса.
Спасибо. Автоинкремент у меня не совсем честный - стоит innodb_autoinc_lock_mode = 2. Но учитывая специфику приложения - полагаться можно. ![]()
Добавлено секционирование по этому полю. ![]()
Почитал. Интересно, что ситуация у человека наоборот: у него при использование префикса многостолбцового индекса возникает USING WHERE, у меня же - только если включить сортировку по второй части индекса ORDER BY `date`. Причём, появляется не USING FILESORT, как если бы эта самая, вторая часть, не подхватывалась, а USING WHERE - типа индекс вообще не используется. Но, при этот, тот же самый EXPLAIN сообщает обратное. ![]()
Если, как Вы считаете, это проблема отображения, то как это правильно проверить? Выполнить запрос несколько раз пока не устаканется время выполнения и последний результат считать правильным? SQL_NO_CACHE, как я понимаю, спасает только от кэша запросов, а более глубокие процессы кэширования принудительно выключить нельзя. Потому как время выполнения запроса в первые разы больше чем в следующие.
Отредактированно rs7 (31.01.2011 04:59:52)
Неактивен

USING WHERE — не означает, что индекс не используется. Это означает,
что результат дополнительно проверяется на соблюдение условий. Наличие
индекса при вытаскивании данных можно увидеть в столбце key. Что касается
Тобиаса — у него ситуация такая же — используется левая часть индекса
(key_len=4, только по _id в Вашем случае), и отображается «Using where».
А что Вы называете более глубокими процессами кэширования? При первом
проходе Вы вытаскиваете с диска страницы индекса, которых еще там не
было. При втором проходе они там уже есть, поэтому на диск за ними идти
не нужно.
Неактивен
Спасибо за ответы.
Неактивен