PostgreSQL
 sql >> база данни >  >> RDS >> PostgreSQL

OFFSET спрямо ROW_NUMBER()

Създадох тест, който сравнява OFFSET, курсорите и ROW_NUMBER(). Впечатлението ми от ROW_NUMBER(), че ще бъде последователно по скорост, независимо къде се намирате в набора от резултати, е правилно. Тази скорост обаче е драстично по-бавна от OFFSET или CURSOR, които, както беше и моето впечатление, са почти еднакви по скорост, като и двете влошават скоростта, колкото повече напредвате към края на резултата.

Резултати:

offset(100,100): 0.016359
scroll(100,100): 0.018393
rownum(100,100): 15.535614

offset(100,480000): 1.761800
scroll(100,480000): 1.781913
rownum(100,480000): 15.158601

offset(100,999900): 3.670898
scroll(100,999900): 3.664517
rownum(100,999900): 14.581068

Тестовият скрипт използва sqlalchemy за настройка на таблици и 1000000 реда тестови данни. След това използва курсор psycopg2, за да изпълни всеки оператор SELECT и да извлече резултати с трите различни метода.

from sqlalchemy import *

metadata = MetaData()
engine = create_engine('postgresql://scott:[email protected]/test', echo=True)

t1 = Table('t1', metadata,
    Column('id', Integer, primary_key=True),
    Column('d1', String(50)),
    Column('d2', String(50)),
    Column('d3', String(50)),
    Column('d4', String(50)),
    Column('d5', String(50))
)

if not engine.has_table('t1'):
    conn = engine.connect()
    t1.create(conn)

    # 1000000 rows
    for i in range(100):
        conn.execute(t1.insert(), [
            dict(
                ('d%d' % col, "data data data %d %d" % (col, (i * 10000) + j))
                for col in range(1, 6)
            ) for j in xrange(1, 10001)
        ])

import time

def timeit(fn, count, *args):
    now = time.time()
    for i in xrange(count):
        fn(*args)
    total = time.time() - now
    print "%s(%s): %f" % (fn.__name__, ",".join(repr(x) for x in args), total)

# this is a raw psycopg2 connection.
conn = engine.raw_connection()

def offset(limit, offset):
    cursor = conn.cursor()
    cursor.execute("select * from t1 order by id limit %d offset %d" % (limit, offset))
    cursor.fetchall()
    cursor.close()

def rownum(limit, offset):
    cursor = conn.cursor()
    cursor.execute("select * from (select *, "
                    "row_number() over (order by id asc) as rownum from t1) as foo "
                    "where rownum>=%d and rownum<%d" % (offset, limit + offset))
    cursor.fetchall()
    cursor.close()

def scroll(limit, offset):
    cursor = conn.cursor('foo')
    cursor.execute("select * from t1 order by id")
    cursor.scroll(offset)
    cursor.fetchmany(limit)
    cursor.close()

print 

timeit(offset, 10, 100, 100)
timeit(scroll, 10, 100, 100)
timeit(rownum, 10, 100, 100)

print 

timeit(offset, 10, 100, 480000)
timeit(scroll, 10, 100, 480000)
timeit(rownum, 10, 100, 480000)

print 

timeit(offset, 10, 100, 999900)
timeit(scroll, 10, 100, 999900)
timeit(rownum, 10, 100, 999900)


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Поточно предаване на PostgreSQL срещу логическа репликация – Сравнение

  2. Как да актуализирам всички колони с INSERT ... ON CONFLICT ...?

  3. Как мога да накарам инсталирането на gem да работи на OS X Lion с Ruby 1.8.7 без сег неизправност?

  4. Изтриване на записи от отдалечена postgresql база данни с помощта на локално предоставен списък

  5. Максимален брой знаци в етикетите (имена на таблици, колони и т.н.)