Простой SQLAlchemy запрос во Flask выполняется очень медленно - PullRequest
0 голосов
/ 03 мая 2018

У меня есть такая таблица:

                             Table "public.transactions"
       Column        |           Type           | Nullable | Default | Storage  |
---------------------+--------------------------+----------+--------------------|
 id                  | integer                  | not null | nextval | plain    |
 ticket              | integer                  |          |         | plain    |
 pay_station         | character varying(50)    |          | extended|          |
 stall               | character varying(50)    |          |         | extended |
 license_plate       | character varying(8)     |          |         | extended |
 purchased_date      | timestamp with time zone | not null |         | plain    |
 expiry_date         | timestamp with time zone |          |         | plain    |
 payment_type        | character varying(50)    |          |         | extended |
 total_collections   | numeric(10,2)            |          |         | main     |
 revenue             | numeric(10,2)            |          |         | main     |
 rate_name           | character varying(50)    |          |         | extended |
 hours_paid          | numeric(4,2)             |          |         | main     |
 validation_revenue  | numeric(10,2)            |          |         | main     |
 transaction_fee     | numeric(10,2)            |          |         | main     |
 method              | character varying(50)    |          |         | extended |
Indexes:
    "transactions_pkey" PRIMARY KEY, btree (id)
    "transactions_expiry_date_idx" btree (expiry_date)
    "transactions_purchased_date_idx" btree (purchased_date)
    "transactions_stall_idx" btree (stall)

И еще ~ 20 столбцов, для краткости опущенных.

В этой таблице ~ 2,5 миллиона строк.

Теперь мой код Python во Flask, который обслуживает API, выглядит следующим образом для примера запроса:

filters = [
    datetime_range['start'] < Transactions.expiry_date,
    datetime_range['end'] > Transactions.purchased_date
]

if 'parking_spaces' in params:
    spaces = params['parking_spaces'] # array
    filters.append(Transactions.stall.in_(spaces))

results = Transactions.query.with_entities(
    Transactions.stall, Transactions.purchased_date, Transactions.expiry_date
    ).filter(*filters).order_by(Transactions.purchased_date).all()

Где даты datetime объекты. Теперь, если я не предоставляю никаких входных данных в теле POST, я по умолчанию устанавливаю минимальное / максимальное время, без пробелов WHERE IN, и запрос выглядит так:

datetime_range: 
{'start': datetime.datetime(2016, 1, 1, 0, 0, tzinfo=datetime.timezone.utc), 'end': datetime.datetime(2019, 1, 1, 0, 0, tzinfo=datetime.timezone.utc)}

Query: 
SELECT transactions.stall AS transactions_stall, transactions.purchased_date AS transactions_purchased_date, transactions.expiry_date AS transactions_expiry_date 
FROM transactions 
WHERE transactions.expiry_date > %(expiry_date_1)s AND transactions.purchased_date < %(purchased_date_1)s ORDER BY transactions.purchased_date

Теперь, если я сделаю запрос непосредственно в psql:

SELECT transactions.stall, transactions.purchased_date, transactions.expiry_date FROM transactions WHERE transactions.expiry_date > '2016-01-01 00:00:00.000Z' AND transactions.purchased_date < '2019-01-01 00:00:00.000Z';

Время: 2724,326 мс (00: 02,724)

Однако, выполняя тот же запрос в SQLAlchemy через Flask, используя Postman для тестирования, я получаю ответ через 866946 мс (14: 26,946) , возвращая 13,4 КБ данных.

Что, очевидно, огромная разница. Когда я настраиваю диапазон, время отклика увеличивается экспоненциально - некоторые образцы:

{
    "datetime_range": {
        "start": "2017-01-01T14:30:00.000Z",
        "end": "2017-01-04T18:00:00.000Z"
    }
}

Время отклика: 13387 мс (00: 13,39)

Тот же запрос в psql:

SELECT transactions.stall, transactions.purchased_date, transactions.expiry_date FROM transactions WHERE transactions.expiry_date > '2017-01-01T14:30:00.000Z' AND transactions.purchased_date < '2017-01-04T18:00:00.000Z';

Время: 580.603 мс

{
    "datetime_range": {
        "start": "2017-01-01T14:30:00.000Z",
        "end": "2017-03-01T18:00:00.000Z"
    }
}

Время ответа SQLAlchemy: 41878 мс

SELECT transactions.stall, transactions.purchased_date, transactions.expiry_date FROM transactions WHERE transactions.expiry_date > '2017-01-01T14:30:00.000Z' AND transactions.purchased_date < '2017-03-01T18:00:00.000Z';

Время отклика PostgreSQL: 1170,169 мс (00: 01,170)

Почему здесь такая огромная разница, и как я могу заставить SQLAlchemy работать быстрее и сохранять время ответа моего Flask порядка секунд, а не минут?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...