2010-06-17 4 views
2

У меня есть временная таблица с около 1 миллиона записей. Временная таблица сохраняет результат большего запроса. Например, я хочу обрабатывать эти записи 1000 за раз. Каков наилучший способ настроить запросы, чтобы получить первые 1000 строк, затем 1000 и т. Д.? Они по сути не упорядочены, но временная таблица имеет только один столбец с идентификатором, поэтому я могу заказать его, если это необходимо. Я думал о создании дополнительного столбца с временной таблицей, чтобы пронумеровать все строки, что-то вроде:получить n записей за раз из временной таблицы

CREATE TEMP TABLE tmptmp AS 
SELECT ##autonumber somehow##, id 
FROM .... --complicated query 

тогда я могу сделать:

SELECT * FROM tmptmp WHERE autonumber>=0 AND autonumber < 1000 

и т.д ... как бы я на самом деле сделать это ? Или есть лучший способ? Я использую Python и PostgreSQL.

+0

Вы можете указать, если вы используете 'pygresql' или' psycopg2' ... – ChristopheD

+0

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

+0

Попробуйте использовать курсоры Postgres и LIMIT start, size. Я могу уточнить, если вы хотите. –

ответ

4

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

http://www.postgresql.org/docs/8.4/interactive/sql-fetch.html

+0

конечно. и из Python мне просто нужно сделать 'cur.fetchmany (1000)' вместо 'cur.fetchall()' heh. – Claudiu

+1

+1 Да, это было бы, конечно, лучшее решение (скоро я удалю шахту). В интерфейсе базы данных, совместимом с 'dbapi2' в Python, вы действительно будете использовать std' .execute (sql) ', за которым следует серия' .fetchmany (1000) ', пока курсор полностью не будет потреблен. – ChristopheD

1

Может быть, вы могли бы использовать что-то вроде этого (мы используем при обновлении партии таблицы с +20 миллионов строк, и не хотим, чтобы заграбастать репликацию).

import sys 
import psycopg2 
from datetime import datetime 

firstid = 0 
splitsize = 50 # Size of each batch 


# Complicated query 
query_complex = """ 
    CREATE TEMP TABLE tmptmp AS 
    SELECT * FROM schema.massive_table 
""" 
# Query to be run at intervals 
query = """ 
    SELECT * FROM tmptmp WHERE id BETWEEN %(startid)s AND %(endid)s 
""" 

conn = psycopg2.connect("dbname=database_name user=postgres") 
curs = conn.cursor() 
# Run complicated query 
curs.execute(query_complex) 
# Get highest id 
curs.execute("SELECT max(id) FROM tmptmp") 
maxid = curs.fetchall()[0][0] 
print "Max id: %s" % maxid 

for startid in range(firstid, maxid, splitsize): 
    endid = startid + splitsize - 1 
    print "%s: Running query on range %s to %s" % (datetime.now(), startid, endid) 
    curs.execute(query, {'startid':startid, 'endid':endid}) 
    print "%s: Affected rows: %s. Total completed: %s%%" % (datetime.now(), curs.rowcount, round((endid * 100)/maxid, 3)) 

print "Done." 

Вывод, который следует:

Max id: 308 
2010-06-18 11:59:11.271000: Running query on range 0 to 49 
2010-06-18 11:59:11.271000: Affected rows: 49. Total completed: 15.0% 
2010-06-18 11:59:11.271000: Running query on range 50 to 99 
2010-06-18 11:59:11.271000: Affected rows: 50. Total completed: 32.0% 
2010-06-18 11:59:11.271000: Running query on range 100 to 149 
2010-06-18 11:59:11.271000: Affected rows: 50. Total completed: 48.0% 
2010-06-18 11:59:11.271000: Running query on range 150 to 199 
2010-06-18 11:59:11.271000: Affected rows: 49. Total completed: 64.0% 
2010-06-18 11:59:11.271000: Running query on range 200 to 249 
2010-06-18 11:59:11.271000: Affected rows: 42. Total completed: 80.0% 
2010-06-18 11:59:11.271000: Running query on range 250 to 299 
2010-06-18 11:59:11.318000: Affected rows: 3. Total completed: 97.0% 
2010-06-18 11:59:11.318000: Running query on range 300 to 349 
2010-06-18 11:59:11.318000: Affected rows: 1. Total completed: 113.0% 
Done. 

// Джон

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