2010-01-08 3 views
6

следующие запрос возвращает данные срочно:Почему postgresql не запускает сразу несколько строк?

SELECT time, value from data order by time limit 100; 

Без предельного пункта, это занимает много времени, прежде чем сервер начнет возвращающуюся строку:

SELECT time, value from data order by time; 

Я наблюдаю это как с помощью инструмента запросов (psql) и при запросе с использованием API.

Вопросы/проблемы:

  • Объем работы сервер должен сделать, прежде чем начать возвращать строки должны быть одинаковыми для обоих операторов выбора. Верный?
  • Если да, то почему существует задержка в случае 2?
  • Есть ли какая-то фундаментальная проблема РСУБД, которую я не понимаю?
  • Есть ли способ, с помощью которого postgresql можно начинать возвращать строки результата клиенту без паузы, также для случая 2?
  • EDIT (см. Ниже). Похоже, что setFetchSize - это ключ к решению этого вопроса. В моем случае я выполняю запрос из python, используя SQLAlchemy. Как установить этот параметр для одного запроса (выполняется session.execute)? Я использую драйвер psycopg2.

Столбец time является основным ключом, кстати.

EDIT:

Я считаю, что это отрывок из JDBC driver documentation описывает проблему и намеки на решение (я все еще нуждаются в помощи - увидеть последнюю пулю элемент списка выше):

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

и

Изменение кода в режиме курсора так просто, как установка размера выборки Заявления до соответствующего размера. Установка размера выборки на 0 приведет к кэшированию всех строк (поведение по умолчанию).

// make sure autocommit is off 
conn.setAutoCommit(false); 
Statement st = conn.createStatement(); 

// Turn use of the cursor on. 
st.setFetchSize(50); 
+0

Какой драйвер вы используете? (вероятно, psycopg2, но, пожалуйста, подтвердите) –

+1

Вы в основном помогли себе. Отлично сработано! –

+0

Да, водитель psycopg2. – codeape

ответ

4

Драйвер psycopg2 dbapi буферизует весь результат запроса перед возвратом любых строк. Вам нужно будет использовать курсор на стороне сервера для постепенного получения результатов. Для SQLAlchemy см. server_side_cursors in the docs, и если вы используете ORM Query.yield_per() method.

SQLAlchemy в настоящее время не имеет возможности установить это для одного запроса, но there is a ticket with a patch for implementing that.

+0

Я попытался использовать серверный курсор: c = conn.cursor ("mycursor"); c.execute ("..."); c.fetchmany (100). Но все же я получаю долгую задержку, прежде чем что-то вернется. Что я делаю не так? – codeape

+0

Предполагая, что conn - это соединение psycopg2, я понятия не имею, работает правильно для меня. Вы можете попробовать выполнить EXPLAIN ANALYZE для одного и того же запроса и посмотреть первый номер для первой строки в выводе объяснения, то есть время postgresql, принятое для поиска первой строки. –

0

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

Я бы ожидал, что эффективная БД заметила бы это и оптимизировала бы ее. Кажется, что PGSQL нет. * shrug *

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

Предлагаю попытаться удалить ЗАКАЗ. Скорее всего, ваши результаты будут правильно упорядочены по времени в любом случае (может даже быть стандарт или спецификация, которая соответствует этому, учитывая ваш ПК), и вы можете быстрее получить свои результаты.

+0

Я считаю, что вы, возможно, неправильно поняли мой вопрос. С помощью LIMIT база данных сразу возвращает эти строки. Без лимита возникает пауза до того, как первые строки будут возвращены клиенту. – codeape

+0

Базы данных могут иметь разные планы запросов, если оптимизатор знает, что вы заинтересованы в результатах как можно быстрее. У Oracle и DB2 есть варианты для этого. Может быть, предельная статья в подсказке Postgresql вызывает подсказку, что запрос немедленно хочет получить результаты? –

+0

Да, сначала я неправильно понял ваш вопрос, поэтому я обновил все это. Посмотрите мой обновленный ответ прямо сейчас! –

Смежные вопросы