флоппик SELECT * FROM table ORDER BY indexed_column LIMIT N1,N2 Типичный пример для использования лимита - здесь можно и с буферизацией, и без буферизации, и мускул отдаст результат очень быстро. Дело не в "подводных камнях", дело в том, что не помешала бы удобная фича, да ее нету.
Nemo, нет, в том то и дело, что обработается N1 + N2. Это в результате N1 строк будут отброшены (после выборки) и вернутся N2
Откуда у тебя возмется «начиная с N1 ?» тебе их надо сначала отсортировать. Потому что ORDER BY. А что бы отсортировать, надо их сначала выбрать все. Только если это уникальный индекс, и если выборка только по одной таблице, и нет условий по другим полям, этого не произойдет.
флоппик Немо прав. Если на поле навешен индекс - мускул сразу найдет N1-ю запись в дереве индекса и дальше начнет отбирать N2 записей, также при помощи индекса. При чем тут уникальный-неуникальный? Насчет других таблиц-других полей не спорю, там все зависит от ситуации. Я привел простой конкретный пример, для которого мускул работает безотказно. Как будет для такого примера работать оракл - хз.
Dagdamor Код (Text): mysql> EXPLAIN SELECT * FROM `users` ORDER BY `US_ID` LIMIT 300, 5; +----+-------------+-------+-------+---------------+---------+---------+------+------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | +----+-------------+-------+-------+---------------+---------+---------+------+------+ | 1 | SIMPLE | users | index | NULL | PRIMARY | 4 | NULL | 428 | +----+-------------+-------+-------+---------------+---------+---------+------+------+ таблица дырявая, правда. rows 428
Хаааа! Пример таблички: [sql]CREATE TABLE IF NOT EXISTS `temp_table` ( `id` int(11) NOT NULL auto_increment, `unq` int(11) NOT NULL, `indx` int(11) NOT NULL, `indx_null` int(11) default NULL, `t1` text NOT NULL, `t2` text NOT NULL, PRIMARY KEY (`id`), UNIQUE KEY `unq` (`unq`), KEY `indx` (`indx`), KEY `idx_null` (`indx_null`) ) ENGINE=MyISAM; [/sql] Генератор строк: PHP: <?php set_time_limit(0); mysql_connect('localhost', 'temp','temp'); mysql_select_db('temp'); $rct = 1000000; $lpt = 0; for ($i=0; $i<=$rct; $i++) { mysql_query('insert into temp_table (unq, indx, indx_null, t1, t2) values ('.$i.','.rand(0,$i).','.(rand(0,1)==1?$i:'NULL').',\'record_'.$i.'\',\'text data\')') or die('error? '.mysql_error()); $cpt = round(($i/$rct)*100); if ($cpt!=$lpt) { echo 'inserted '.$cpt.'%, '.$i.' records.<br/>'; $lpt = $cpt; } } ?> Запрос: [sql]EXPLAIN SELECT * FROM `temp_table` LIMIT 1, 30[/sql] дает нам... Код (Text): mysql> select count(*) from temp_table; +----------+ | count(*) | +----------+ | 1000001 | +----------+ 1 row in set (0.00 sec) mysql> EXPLAIN SELECT * FROM `temp_table` LIMIT 1, 30; +----+-------------+------------+------+---------------+------+---------+------+---------+-------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+------------+------+---------------+------+---------+------+---------+-------+ | 1 | SIMPLE | temp_table | ALL | NULL | NULL | NULL | NULL | 1000001 | | +----+-------------+------------+------+---------------+------+---------+------+---------+-------+ 1 row in set (0.00 sec) mysql>
Продолжаем эксперименты: Код (Text): mysql> explain select * from temp_table where indx_null >3000 order by indx_null desc limit 4000, 30; +----+-------------+------------+-------+---------------+----------+---------+------+--------+-------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+------------+-------+---------------+----------+---------+------+--------+-------------+ | 1 | SIMPLE | temp_table | range | idx_null | idx_null | 5 | NULL | 786513 | Using where | +----+-------------+------------+-------+---------------+----------+---------+------+--------+-------------+ 1 row in set (0.00 sec) mysql>
Да, я был неправ. Даже использование ПК не спасает ситуацию. Заметьте, в селекте сейчас всего одно поле - ПК! Код (Text): mysql> explain select id from temp_table where id<500000 order by id limit 1000000, 1; +----+-------------+------------+-------+---------------+---------+---------+------+--------+--------------------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+------------+-------+---------------+---------+---------+------+--------+--------------------------+ | 1 | SIMPLE | temp_table | range | PRIMARY | PRIMARY | 4 | NULL | 530229 | Using where; Using index | +----+-------------+------------+-------+---------------+---------+---------+------+--------+--------------------------+ 1 row in set (0.00 sec) mysql>
аа так, вот оно что 0о Понятно, значит Олег использует Оракул а все остальные Мускуль? ну эт значит надолго...
Я использую и то, и другое. Я пытаюсь показать, что не надо фетешировать на некоторые конструкции, и говорить «Мускул лучше, ведь в нем есть лимит!»
Просто надо с осторожность использовать limit, особенно, если проект нагруженный. Об этом есть на хабре статьи, называются mysql tricks (что-то вроде этого)
флоппик Luge Дался вам этот эксплайн, тем более поле rows. Вы скорость замерьте. А что, есть возражения? Ведь действительно лучше, ибо с ним удобнее. Что в качестве замены лимита предлагает Оракл - это что-то с чем-то. Вот там действительно выборка всей хрени целиком + отрезание лишнего.
Неа. Оптимизатор учитывает в плане запроса то, что ты называешь хренью. Костыль он и в африке костыль...