[ Поиск ] - [ Пользователи ] - [ Календарь ]
Полная Версия: Что быстрее, выбрать все записи или с LIMIT ?
Страницы: 1, 2, 3
S.Chushkin
Цитата (vasa_c @ 5.02.2013 - 15:47)
Есть результаты тестов?

Без понятия.
Вообще, я верю разработчикам. Если они говорят что быстрее, значит быстрее. ... до тех пор, пока не доказано обратное. Не помню, чтобы видел такие доказательства.

Цитата
Если мы выбираем по упорядоченному индексу с, допустим, LIMIT 10,10, будет ли влиять на скорость общее количество строк?

Конечно. Почитайте доку по SQL_CALC_FOUND_ROWS, как это работает.

_____________
Рекламка / ad.pesow.com Хрень / mr-1.ru
vasa_c
Цитата
Вообще, я верю разработчикам. Если они говорят что быстрее, значит быстрее. ... до тех пор, пока не доказано обратное. Не помню, чтобы видел такие доказательства.

пруф на то, где они это говорят

Цитата
Конечно. Почитайте доку по SQL_CALC_FOUND_ROWS, как это работает.

хорошо, а при COUNT() это будет влиять?

_____________
Блог ГО | Таблица символов Юникода | Графомания
S.Chushkin
Цитата (vasa_c @ 5.02.2013 - 16:21)
пруф на то, где они это говорят

Да не помню я, давно это было, когда решал пользовать или нет. А искать заново - лень.

Цитата
хорошо, а при COUNT() это будет влиять?

Конечно.

По сути работа с SQL_CALC_FOUND_ROWS и с COUNT(*) похожи:
- в первом случае 1 тяжёлый запрос + 1 очень лёгкий
- во втором 2 тяжёлых
По моей практике раз на раз не приходится, - чаще всего с SQL_CALC_FOUND_ROWS работает быстрее, ибо запросы оптимизированы, но бывает что с COUNT(*) работает быстрее. И насколько помню, зависит от "времени и пространства", - самого запроса, формата и количества данных, структуры индексов, версии mySQL, его настроек. (по совокупности)


_____________
Рекламка / ad.pesow.com Хрень / mr-1.ru
Valick
S.Chushkin, я сегодня проверял (правда без индекса еще не тестил, но ктож не индексирует нужные поля) на 4 миллионах строк, SQL_CALC_FOUND_ROWS 0.05 а COUNT(*)+сама выборка 0.007

_____________
Стимулятор ~yoomoney - 41001303250491
killer8080
Valick
на какой версии тестил?
Интересно узнать изменилось ли что то в 5.5.
S.Chushkin
Цитата (Valick @ 5.02.2013 - 21:19)
S.Chushkin, я сегодня проверял (правда без индекса еще не тестил, но ктож не индексирует нужные поля) на 4 миллионах строк, SQL_CALC_FOUND_ROWS 0.05 а COUNT(*)+сама выборка 0.007

Ещё раз, - зависит от конкретики. Без структуры данных, запросов, версии и настроек движка что-то умное сказать по этому поводу сложно.

_____________
Рекламка / ad.pesow.com Хрень / mr-1.ru
S.Chushkin
Работать лень, решил малость потестить :)

Тест 1.
Сравнительное время по двум типам выборки:
0.01126 0.05095     0.06809
0.01672 0.0559 0.06666
0.01681 0.12992 0.06612
0.01662 0.03822 0.06063
0.01669 0.05492 0.06753
0.01672 0.05797 0.07956
0.01671 0.04828 0.06796
0.01662 0.05198 0.0628
0.01157 0.03486 0.07061
0.01678 0.05216 0.07406
0.01691 0.05411 0.07342
0.01662 0.04737 0.06218
0.01672 0.04627 0.08023
0.01667 0.05688 0.0652
0.0166 0.04646 0.06475

0.01600 0.05508
0.07108 0.06865


где,
1-й столбец: select sql_no_cache COUNT(*) from Sessions where UserID > 30 order by UserID;
2-й столбец: select sql_no_cache * from Sessions where UserID > 30 order by UserID limit 20000,100;
3-й столбец: select SQL_CALC_FOUND_ROWS sql_no_cache * from Sessions where UserID > 30 order by UserID limit 20000,100;
нижняя строка - среднее по 15 выборкам
Выборка 1: Innodb_rows_read# 31962 + 20100 (The number of rows read from Innodb tables)
Выборка 2: Innodb_rows_read# 31962

Параметры теста...
Выборка 1:
select sql_no_cache COUNT(*) from Sessions where UserID > 30 order by UserID;
select sql_no_cache * from Sessions where UserID > 30 order by UserID limit 20000,100;

Выборка 2:
select SQL_CALC_FOUND_ROWS sql_no_cache * from Sessions where UserID > 30 order by UserID limit 20000,100;
select found_rows(); -- можно пренебреч, т.к. время выполнения ~0.0001 сек.


Win 7, mySQL 5.5.27 64x, InnoDB, innodb_buffer_pool_size = 256M (остальное по умолчанию)
таблица: 1238141 записей, ~211M, индекс по UserID есть

Вывод: Второй вариант выборки чуть быстрее, на 3.5%, что можно считать несущественным. Т.е. - скоростя равны.


_____________
Рекламка / ad.pesow.com Хрень / mr-1.ru
S.Chushkin
Тест 2.
Сравнительное время по двум типам выборки:
0.01656 0.01149     0.01794
0.01112 0.00783 0.01798
0.01657 0.01154 0.01819
0.01659 0.01154 0.01796
0.01664 0.00768 0.01795
0.01655 0.01152 0.01809
0.0166 0.01154 0.018
0.01654 0.01158 0.01803
0.0166 0.01157 0.01802
0.01658 0.0117 0.01297
0.01664 0.01156 0.01817
0.01665 0.01153 0.01799
0.01652 0.00828 0.01145
0.01658 0.01165 0.01799
0.01543 0.01168 0.01806

0.01614 0.01084
0.02699 0.01725


Параметры теста...
Выборка 1:
select sql_no_cache COUNT(*) from Sessions where UserID > 30 order by UserID;
select sql_no_cache UserID from Sessions where UserID > 30 order by UserID limit 20000,100;
Выборка 2:
select SQL_CALC_FOUND_ROWS sql_no_cache UserID from Sessions where UserID > 30 order by UserID limit 20000,100;
select found_rows();

Остальное как в 1-ом тесте.

Вывод: Второй вариант выборки быстрее на 36%, что уже "заметно быстрее".

п.с.
Эти два теста показывают "зависимость от конкретики", в частности от самого запроса.
Тест конечно синтетический, но всё же...


_____________
Рекламка / ad.pesow.com Хрень / mr-1.ru
killer8080
S.Chushkin
можешь повторить эти тесты, но с реальным лимитом, скажем 20. ИМХО тест не объективен, т.к. большая часть времени потрачена на извлечение данных, а не на подсчет, в реальных условиях такие огромные лимиты большая редкость.

PS за тест спасибо.
vasa_c
У меня такое получилось, может где накосячил.

Пагинация по первичному ключу.
mysql-5.5, php-mysqli, ubuntu
таблица - 2,3М записей, тип - MyISAM

цикл с возрастающим лимитом:

for ($i = 0; $i < 1000000; $i += 50) {
$query1 = 'SELECT SQL_NO_CACHE COUNT(1) FROM `categories_logs`';
$query2 = 'SELECT SQL_NO_CACHE `log_id`,`time` FROM `categories_logs` ORDER BY `log_id` LIMIT '.$i.',10';
}


Результаты (время в мкс):

LIMIT 0,10: 221 723
LIMIT 50,10: 375 944
LIMIT 100,10: 375 1127
LIMIT 150,10: 288 1357
LIMIT 200,10: 288 1738
LIMIT 250,10: 375 2039
LIMIT 300,10: 396 2321
LIMIT 350,10: 394 2660
LIMIT 400,10: 391 2716
LIMIT 450,10: 349 1835
LIMIT 500,10: 388 1798
LIMIT 550,10: 243 1579
LIMIT 600,10: 133 1705
LIMIT 650,10: 152 1773
LIMIT 700,10: 125 1902
LIMIT 750,10: 128 2005
LIMIT 800,10: 133 2120
LIMIT 850,10: 128 2249
LIMIT 900,10: 138 2372
LIMIT 950,10: 128 3741


С большим лимитом:

LIMIT 0,10: 157 302
LIMIT 100000,10: 133 1164391
LIMIT 200000,10: 226 1661092
LIMIT 300000,10: 227 1794438
LIMIT 400000,10: 216 1761606


COUNT'у наплевать, а SELECT от лимита начинает пухнуть.

Теперь запрос:

$query1 = 'SELECT SQL_CALC_FOUND_ROWS SQL_NO_CACHE `log_id`,`time` FROM `categories_logs` ORDER BY `log_id` LIMIT '.$i.',10';



LIMIT 0,10: 1755471
LIMIT 50,10: 1768442
LIMIT 100,10: 2110744


EXPLAIN нам объясняет - SQL_CALC_FOUND_ROWS сканит всю таблицу, не используя ключи.

Итого, вывод: если выборка простая с использованием ключей - быстрее SELECT + COUNT. Если выборка долгая и хитрожопая, лучше SQL_CALC_FOUND_ROWS.

Размер таблицы на простой SELECT не влияет, на него влияет LIMIT. Если хотите целиком пропагинировать большую таблицу, то лучше использовать не LIMIT, а что-нибудь вроде WHERE `id`>10000.

А вот в InnoDB с COUNT'ом всё похуже - http://www.mysqlperformanceblog.com/2006/1...-innodb-tables/

_____________
Блог ГО | Таблица символов Юникода | Графомания
S.Chushkin
Цитата (killer8080 @ 6.02.2013 - 10:32)
S.Chushkin
можешь повторить эти тесты, но с реальным лимитом, скажем 20. ИМХО тест не объективен, т.к. большая часть времени потрачена на извлечение данных, а не на подсчет, в реальных условиях такие огромные лимиты большая редкость.

100 записей это "огромные"?!
Вы что-то попутали, 100 "строк" на страницу это не редко используют. Бывает и больше.
с 20-ю записями, переданными на клиент, конечно будет чуть быстрее, но незначительно.
Будет время - попытаю.

_____________
Рекламка / ad.pesow.com Хрень / mr-1.ru
S.Chushkin
Цитата (vasa_c @ 6.02.2013 - 11:57)

Итого, вывод: если выборка простая с использованием ключей - быстрее SELECT + COUNT. Если выборка долгая и хитрожопая, лучше SQL_CALC_FOUND_ROWS.

Ваш тест как раз показывает зависимость результата от самой выборки и от движка. Вспомните, - COUNT() по всей таблице в myISAM просто берёт число значений, в InnoDB просчитывает. SQL_CALC_FOUND_ROWS по всей таблице не имеет смысла делать, ибо эта опция заставляет движок просматривать всю таблицу, подсчитывая число строк. Или, уберите из запроса `time` и он будет использовать ключ.
п.с.
Собственно, как я и говорил выше, пользовать тот или иной вариант выборки, зависит от конкретики.

Цитата
Размер таблицы на простой SELECT не влияет, на него влияет LIMIT.

На самом деле размер (число записей) влиет. Просто при выборке по ключу этого незаметно (вспомните - там зависимость логарифмическая).

_____________
Рекламка / ad.pesow.com Хрень / mr-1.ru
S.Chushkin
>> Будет время - попытаю.
Попытал...

Тест 3.
Сравнительное время по двум типам выборки:
0.01664 0.04682     0.06949
0.01664 0.06124 0.07152
0.01664 0.06124 0.06644
0.0166 0.04364 0.06725
0.01654 0.04727 0.06641
0.01654 0.05261 0.07353
0.01658 0.05524 0.06606
0.01224 0.06237 0.06433
0.01659 0.05178 0.06809
0.01661 0.05109 0.07479
0.01654 0.05126 0.07752
0.01657 0.05147 0.0673
0.01668 0.06086 0.06234
0.01657 0.04642 0.06494
0.01688 0.04631 0.06611

0.01632 0.05264
0.06896 0.06840

Разница с 1-ым тестом только в "limit 20000,20".
Вывод: Разницы с 20 или 100 практически нет.

Тест 4.
Сравнительное время по двум типам выборки:
0.01686 0.01133     0.01779
0.0166 0.01133 0.01821
0.01653 0.01134 0.01584
0.01655 0.01142 0.01787
0.01654 0.01131 0.01787
0.01656 0.01136 0.01794
0.01657 0.01138 0.01785
0.01661 0.01141 0.01781
0.01666 0.0114 0.01781
0.01662 0.01137 0.01785
0.01666 0.01134 0.01785
0.01659 0.01135 0.01785
0.01659 0.01133 0.0179
0.01654 0.0114 0.01784
0.0166 0.01147 0.01786

0.016605333 0.011369333
0.027974667 0.017742667

Разница со 2-ым тестом только в "limit 20000,20".
Вывод: Разницы с 20 или 100 практически нет.

_____________
Рекламка / ad.pesow.com Хрень / mr-1.ru
S.Chushkin
Ещё тройка тестов.
Сравнение времени на выборку первой страницы и последней (стр.12381).

Тест 5.
0.01658 0.00158     0.0678
0.0166 0.00159 0.06644
0.01668 0.00166 0.0624
0.01657 0.0016 0.07076
0.01662 0.00163 0.0724
0.01288 0.00171 0.06966
0.01665 0.00156 0.07194
0.01651 0.00161 0.07982
0.01654 0.00155 0.06483
0.01652 0.00162 0.06985

0.01622 0.00161
0.01783 0.06959

Параметры теста...
Выборка 1:
select sql_no_cache COUNT(*) from Sessions where UserID > 1 order by UserID;
select sql_no_cache * from Sessions where UserID > 1 order by UserID limit 0,100;
Выборка 2:
select SQL_CALC_FOUND_ROWS sql_no_cache * from Sessions where UserID > 1 order by UserID limit 0,100;
select found_rows();

Остальное как в 1-ом тесте.

Вывод: С COUNT() заметно быстрее (почти в 4 раза).
(по сути, я считаю, что это недоделка в движке, - в данном случае с SQL_CALC_FOUND_ROWS не используется индекс там, где это нужно/возможно и из-за этого "тормозит")

Тест 6.
0.31788 1.78517     1.03159
0.28836 1.79201 1.04967
0.29821 1.77604 1.02951
0.29696 1.79353 1.03597
0.29722 1.79677 1.03616
0.30075 1.78779 1.03451
0.29046 1.78084 1.03236
0.29743 1.78502 1.06257
0.29066 1.78863 1.03767
0.29001 1.7804 1.02766

0.29679 1.78662
2.08341 1.03777

Разница с 5-ым тестом только в "1238100,100".
Вывод: С SQL_CALC_FOUND_ROWS быстрее в 2 раза.
(а тут что-то странное - непонятно почему выборка с SQL_CALC_FOUND_ROWS быстрее, чем без него в 1.7 раза)

Тест 7.
0.29679 0.30752     0.31207
0.29529 0.32024 0.32074
0.28601 0.32248 0.31283
0.30048 0.30629 0.31314
0.28395 0.3135 0.31649
0.29298 0.3123 0.34535
0.29131 0.32171 0.31229
0.29181 0.3532 0.32031
0.2973 0.34527 0.31394
0.28387 0.32198 0.32176

0.29198 0.32245
0.61443 0.31889

Разница с 6-ым тестом - вместо * конкретное поле UserID (индексное).
Вывод: С SQL_CALC_FOUND_ROWS быстрее в 2 раза.

В общем, как-то так...

_____________
Рекламка / ad.pesow.com Хрень / mr-1.ru
Быстрый ответ:

 Графические смайлики |  Показывать подпись
Здесь расположена полная версия этой страницы.
Invision Power Board © 2001-2025 Invision Power Services, Inc.