sql >> Databasteknik >  >> RDS >> PostgreSQL

Förbättring av OFFSET-prestanda i PostgreSQL

Du kanske vill ha ett beräknat index.

Låt oss skapa en tabell:

create table sales(day date, amount real);

Och fyll den med några slumpmässiga saker:

insert into sales 
    select current_date + s.a as day, random()*100 as amount
    from generate_series(1,20);

Indexera det per dag, inget speciellt här:

create index sales_by_day on sales(day);

Skapa en radpositionsfunktion. Det finns andra tillvägagångssätt, det här är det enklaste:

create or replace function sales_pos (date) returns bigint 
   as 'select count(day) from sales where day <= $1;' 
   language sql immutable;

Kontrollera om det fungerar (kalla det inte så här på stora datamängder dock):

select sales_pos(day), day, amount from sales;

     sales_pos |    day     |  amount  
    -----------+------------+----------
             1 | 2011-07-08 |  41.6135
             2 | 2011-07-09 |  19.0663
             3 | 2011-07-10 |  12.3715
    ..................

Nu den knepiga delen:lägg till ytterligare ett index beräknat på sales_pos-funktionsvärdena:

create index sales_by_pos on sales using btree(sales_pos(day));

Så här använder du det. 5 är din "offset", 10 är "limit":

select * from sales where sales_pos(day) >= 5 and sales_pos(day) < 5+10;

        day     | amount  
    ------------+---------
     2011-07-12 | 94.3042
     2011-07-13 | 12.9532
     2011-07-14 | 74.7261
    ...............

Det är snabbt, för när du kallar det så här använder Postgres förberäknade värden från indexet:

explain select * from sales 
  where sales_pos(day) >= 5 and sales_pos(day) < 5+10;

                                    QUERY PLAN                                
    --------------------------------------------------------------------------
     Index Scan using sales_by_pos on sales  (cost=0.50..8.77 rows=1 width=8)
       Index Cond: ((sales_pos(day) >= 5) AND (sales_pos(day) < 15))

Hoppas det hjälper.



  1. Hur man skapar en klon av ditt MySQL- eller PostgreSQL-databaskluster

  2. Behöver köra en sql-fråga mot två Oracle DBs i skalskript åt gången och exportera data till separata csv-filer

  3. Hur man lagrar sqlite-databas direkt på sdcard

  4. Vilken är den korrekta kodningen / escape / html-entiteterna som behövs när du skickar data från js till php, php till mysql och för REST json-svar