sql >> データベース >  >> RDS >> PostgreSQL

オフセットと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ステートメントを実行し、3つの異なるメソッドで結果をフェッチします。

    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. SQLServerのTempDBファイルの場所の変更

    2. OracleTriggerWHEN句の例

    3. select * from table vs select colA、colB、etc. from table Interesting Behavior in SQL Server 2005

    4. MySQL/MariaDBデータベースの自動インクリメント値を変更する方法