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

Форум MySQL

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

 

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

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

тема: производительность SQL_CALC_FOUND_ROWS
 
 автор: 1999   (08.10.2009 в 00:40)   письмо автору
 
 

Доброй ночи!

Все не могу сделать выбор между двумя стандартными ситуациями для пагинации

Вариант1:
1) SELECT COUNT(*) .... - получили кол-во записей
2) SELECT ... LIMIT - получили лимитированное количество записей

Вариант2:
1) SELECT SQL_CALC_FOUND_ROWS * ... LIMIT - получили лимитированное количество записей
2) SELECT FOUND_ROWS() - получили кол-во записей

http://softtime.ru/forum/read.php?id_forum=3&id_theme=49177
Тут об этом говорилось, но на каком-то уровне не том

Вопрос в чем - для MyISAM насколько я понимаю разница между двумя вариантами будет невелика, поскольку запрос COUNT(*) будет дешевым. А вот для других таблиц уже будет что-то иначе. Вопрос - будет ли?

Хотелось бы услышать комментарий cheops'а или Трианона... Если можно

  Ответить  
 
 автор: cheops   (08.10.2009 в 00:48)   письмо автору
 
   для: 1999   (08.10.2009 в 00:40)
 

COUNT(*) дешев если не требуется перебора таблицы, если у вас отсутствует условие WHERE, особенно, если в условии используются неиндексированные столбцы.

  Ответить  
 
 автор: 1999   (08.10.2009 в 00:53)   письмо автору
 
   для: cheops   (08.10.2009 в 00:48)
 

Ага, т.е. если в WHERE стоят неиднексированные столбцы, то использовать COUNT(*) не рекомендуется? Это касается только MyISAM или всех таблиц?

А что насчет InnoDB? ПРосто насколько я помню в ней использование COUNT(*) вобще физически противопоказано... Или нет?

  Ответить  
 
 автор: Trianon   (08.10.2009 в 00:51)   письмо автору
 
   для: 1999   (08.10.2009 в 00:40)
 

Трудоемкость запроса SELECT COUNT(*) зависит не столько от типа таблицы, сколько от того, какими условиями он нафарширован. А ведь внутри SELECT может быть довольно сложный запрос. Может и не быть.

В некоторых случаях агрегатный запрос SELECT COUNT(*) адекватный исходному, просто крайне тяжело составить.

Опять же если таблица относительно короткая (тысячи .. десятки тысяч строк) - ситуация одна.
Если достаточно длинная (десятки ... сотни миллионов строк) - несколько другая.

А выбирать всё равно Вам. Однозначного ответа нет.

  Ответить  
 
 автор: 1999   (08.10.2009 в 00:56)   письмо автору
 
   для: Trianon   (08.10.2009 в 00:51)
 

Немного не понял наверное ваш комментарий. В общем случае да, запросы сложные.. И 2 раза писать одно и то же (я о варианте1) удручает.

Еще вопрос - в чем разница между таблицей с десятками тысяч строк и таблицей с миллионами? Просто я пока работаю (в основном) с таблицами с сотнями тысяч записей... Как раз на перепутье :)

  Ответить  
 
 автор: Trianon   (08.10.2009 в 01:03)   письмо автору
 
   для: 1999   (08.10.2009 в 00:56)
 

По поводу InnoDB - то что я и говорил. Надо просто понимать суть.
http://denis.boltikov.ru/2008/03/12/count-dlya-tablic-innodb-perevod-s-mysql-performance-blog/

>И 2 раза писать одно и то же (я о варианте1) удручает.
Ну иногда исходный SELECT-запрос сам по себе агрегирующий. И натягивать на него сверху COUNT(*) - неминуемый сложный запрос с непонятно каким планом... короче, SQL_CALC_FOUND_ROWS - сильно приманивает.

C другой, SQL_CALC_FOUND_ROWS будет заставлять сервер генерировать все строки результата, в том числе и после конца запрошенного LIMIT-диапазона - просто выводить их клиенту не будет.
И если строк ОЧЕНЬ много, то...

А Вам проще сравнить бенчмарки.

  Ответить  
 
 автор: 1999   (08.10.2009 в 01:07)   письмо автору
 
   для: Trianon   (08.10.2009 в 01:03)
 

> короче, SQL_CALC_FOUND_ROWS - сильно приманивает.
вот-вот, я о том же

> C другой, SQL_CALC_FOUND_ROWS будет заставлять сервер генерировать все строки результата, в том числе и после конца запрошенного LIMIT-диапазона - просто не выводить их клиенту не будет.
оО вот отсюда поподробнее.... т.е. по сути SQL_CALC_FOUND_ROWS просто делает полный селект, а пользователю выдает обрубленную его часть??? Не верю... Тогда же теряется вся его суть!..

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

  Ответить  
 
 автор: Trianon   (08.10.2009 в 01:11)   письмо автору
 
   для: 1999   (08.10.2009 в 01:07)
 

>.е. по сути SQL_CALC_FOUND_ROWS просто делает полный селект, а пользователю выдает обрубленную его часть???

Это свойство вовсе не SQL_CALC_FOUND_ROWS
Это свойство LIMIT в принципе.
Правда простой LIMIT, дойдя до конца диапазона, всё же затыкается.
А считающий - шлёпает дальше.

  Ответить  
 
 автор: 1999   (08.10.2009 в 01:23)   письмо автору
 
   для: Trianon   (08.10.2009 в 01:11)
 

Мде.... Можно тогда я приведу пример?
Есть таблица со 100 записями

2 запроса

1) SELECT * FROM table WHERE ... LIMIT 10,10
2) SELECT * FROM table WHERE ... LIMIT 60,10

Получается при использовании SQL_CALC_FOUND_ROWS первый запрос работает намного дольше второго?

  Ответить  
 
 автор: Trianon   (08.10.2009 в 10:23)   письмо автору
 
   для: 1999   (08.10.2009 в 01:23)
 


gen - время формирования и сортировки строк 
out - время выдачи строк клиенту
  
SELECT * FROM tbl_100 |    обычный           | с SQL_CALC_FOUND_ROWS 
----------------------+----------------------+----------------------
WHERE ... LIMIT 10,10 | gen*(10+10) + out*10 | gen*100 + out*10
WHERE ... LIMIT 60,10 | gen*(60+10) + out*10 | gen*100 + out*10

  Ответить  
 
 автор: 1999   (08.10.2009 в 11:27)   письмо автору
 
   для: Trianon   (08.10.2009 в 10:23)
 

Можно если не трудно пруфлинк? Или это ваш бенч?

  Ответить  
 
 автор: Trianon   (08.10.2009 в 21:20)   письмо автору
 
   для: 1999   (08.10.2009 в 11:27)
 

Это лично мое

  Ответить  
 
 автор: cheops   (08.10.2009 в 01:12)   письмо автору
 
   для: 1999   (08.10.2009 в 01:07)
 

>В то же время понимаю, что уходить с MyISAM нужно.
Можно потерять в скорости и много... MyISAM проще, но быстрее.

  Ответить  
 
 автор: 1999   (08.10.2009 в 01:25)   письмо автору
 
   для: cheops   (08.10.2009 в 01:12)
 

Насколько я понимаю, у MyISAM очень большое количество недостатков (навскидку только приведу отсутствие блокировок и транзакций), которых нет в других СУБД (PostgreSQL) или таблицах (InnoDB). InnoDB насколько я помню тоже не считается идеальной?.. Тогда в какую сторону следует смотреть?

  Ответить  
 
 автор: cheops   (08.10.2009 в 01:39)   письмо автору
 
   для: 1999   (08.10.2009 в 01:25)
 

От задачи зависит, например, тут на форуме транзакции вообще не нужны, если вы работаете толстым клиентом с базой данных, хранящей реальные депозиты - наплевать на всю скорость, лучше сервер помощнее купить, чем отказываться от транзакций.

Это как при выборе языка программирования - лучше выбирать тот язык, который больше всего подходит для решения задачи, а не тот, который лучше всего знаешь.

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

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