Насколько повышается производительность при использовании LIMIT в предложении SQL?

#sql #database #take

#sql #База данных #возьмите

Вопрос:

Предположим, у меня в базе данных есть таблица с 1.000.000 записями.

Если я выполняю:

 SELECT * FROM [Table] LIMIT 1000
  

Займет ли этот запрос столько же времени, как если бы у меня была эта таблица с 1000 записями и я просто выполнял:

 SELECT * FROM [Table]
  

?

Я не ищу, займет ли это точно такое же время. Я просто хочу знать, займет ли выполнение первого намного больше времени, чем второго.

Я сказал 1.000.000 записи, но это могло быть 20.000.000 . Это был просто пример.

Редактировать:
Конечно, при использовании LIMIT и без его использования в одной таблице запрос, созданный с использованием LIMIT, должен выполняться быстрее, но я не об этом спрашиваю…

Чтобы сделать его универсальным:

Table1 : X записи
Table2 : Y записи

(X << Y)

Что я хочу сравнить, так это:

SELECT * FROM Table1

и

SELECT * FROM Table2 LIMIT X

Правка 2:
Вот почему я спрашиваю об этом:

У меня есть база данных с 5 таблицами и связями между некоторыми из них. Одна из этих таблиц будет (я уверен на 100%) содержать около 5.000.000 записей. Я использую SQL Server CE 3.5, Entity Framework в качестве ORM и LINQ для SQL для выполнения запросов.

Мне нужно выполнить в основном три вида непростых запросов, и я думал о том, чтобы показать пользователю ограничение записей (точно так же, как это делают многие веб-сайты). Если пользователь хочет просмотреть больше записей, у него есть возможность еще больше ограничить поиск.

Итак, вопрос возник, потому что я думал о том, чтобы сделать это (ограничить количество X записей на запрос) или сохранить в базе данных только X результаты (последние), что потребует выполнения некоторых удалений в базе данных, но я просто подумал…

Итак, эта таблица может содержать 5.000.000 записи или больше, и чего я не хочу, так это показывать пользователю 1000 или около того, и даже таким образом запрос все равно будет таким же медленным, как если бы он возвращал 5.000.000 строки.

Комментарии:

1. что делает TAKE ключевое слово? Я никогда с этим не сталкивался. это синоним LIMIT ?

2. @wired00 Извините. Я думал о LINQ : / Я отредактирую это 🙂

3. ОГРАНИЧЕНИЕ касается только MySQL. Вероятно, следует пометить это так.

4. @Stephen я считаю, что LIMIT есть и в PostgresSQL 🙂

5. @wired00: Вы правы, LIMIT поддерживается PostgreSQL и TOP является только TSQL / SQL Server. FETCH FIRST x ROWS ONLY теперь это ANSI, но DB2 — единственный, кто реализует IIRC

Ответ №1:

TAKE 1000 из таблицы с 1000000 записями — будет в 1000000/1000 ( = 1000 ) раз быстрее, потому что для этого нужно всего лишь просмотреть (и вернуть) 1000/1000000 записей. Поскольку он выполняет меньше, он, естественно, быстрее.

Результат будет довольно (псевдо-) случайным, поскольку вы не указали порядок, в котором следует ВЫПОЛНЯТЬ. Однако, если вы вводите порядок, то одно из двух приведенных ниже становится истинным:

  1. Предложение ORDER BY следует за индексом — приведенное выше утверждение по-прежнему верно.
  2. Предложение ORDER BY не может использовать какой-либо индекс — это будет лишь незначительно быстрее, чем без TAKE, потому что
    • он должен проверять ВСЕ записи и сортировать по ORDER BY
    • доставьте только подмножество (ПРИМИТЕ во внимание)
    • таким образом, на первом шаге это не быстрее, но на втором шаге требуется меньше операций ввода-вывода / сети, чем для ВСЕХ записей

Если вы ВОЗЬМЕТЕ 1000 записей из таблицы из 1000 записей, это будет эквивалентно (с небольшими существенными отличиями) взятию 1000 записей из 1 миллиарда, при условии, что вы соблюдаете случай (1) отсутствия порядка по или (2) порядка по индексу

Комментарии:

1. таким образом, это означает, что если столбец A не проиндексирован, и я делаю ORDER BY в этом столбце, запрос к одной и той же базе данных с LIMIT X и без него будет довольно схожим с точки зрения производительности, потому что для его сортировки потребуется загрузить все данные, а затем вернуть первые X записи?

2. Быстрее делать что? Если это где-то передает результат, то это ограниченный ввод-вывод, и база данных в значительной степени не имеет значения.

3. @Oscar / Если вы используете ORDER BY someunindexedcolumn LIMIT X (или TAKE, или TOP, или FETCH FIRST и т.д.), Вам нужно будет перетащить все записи, отсортировать их, прежде чем возвращать X записей. Я лгу — если это 1000 из 1 миллиарда, сетевой трафик значительно отличается. В любом случае, вы получаете представление о задействованных шагах и о том, как работает X.

Ответ №2:

Предполагая, что обе таблицы эквивалентны с точки зрения индекса, размера строк и других структур. Также предполагается, что вы используете эту простую инструкцию SELECT . Если у вас есть ORDER BY предложение в ваших SQL-операторах, то, очевидно, что большая таблица будет работать медленнее. Я полагаю, вы спрашиваете не об этом.

Если X = Y, то, очевидно, они должны выполняться с одинаковой скоростью, поскольку механизм запросов будет просматривать записи в точно таком же порядке — в основном сканирование таблицы — для этого простого оператора SELECT . В плане запроса не будет никакой разницы.

Если Y > X только немного, то и скорость аналогичная.

Однако, если Y >> X (что означает, что у Y намного больше строк, чем у X), то версия LIMIT МОЖЕТ быть медленнее. Не из-за плана запроса — опять же, должно быть то же самое — а просто потому, что внутренняя структура компоновки данных может иметь еще несколько уровней. Например, если данные хранятся в виде листьев в дереве, может быть больше уровней дерева, поэтому для доступа к тому же количеству страниц может потребоваться немного больше времени.

Другими словами, 1000 строк могут храниться на 1 уровне дерева, скажем, на 10 страницах. 1000000 строк могут храниться на 3-4 уровнях дерева на 10000 страницах. Даже при использовании только 10 страниц из этих 10000 страниц механизму хранения все равно приходится проходить 3-4 уровня дерева, что может занять немного больше времени.

Теперь, если механизм хранения хранит страницы данных последовательно или, скажем, в виде связанного списка, то разницы в скорости выполнения не будет.

Ответ №3:

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

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

Спасибо за разъяснение.

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

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

MySQL имеет модификаторы LIMIT и OFFSET (# начальной записи), в первую очередь, для точной цели создания фрагментов списка для подкачки, как вы описываете.

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