я бить головой об этом со вчерашнего дня, и я не understanf, что происходит:Простой запрос поиска очень медленно на Postgres, быстро в MySQL
Я заселение размерную схему для проекта datawarehousing, используя Pentaho Kettle для выполнения «поиска/обновления измерения», который в основном ищет существующие строки в таблице измерений, вставляя те, которые не существуют и возвращают технический ключ.
Сама таблица измерения очень прост:
CREATE TABLE dim_loan
(
_tech_id INTEGER NOT NULL,
loan_id INTEGER,
type TEXT,
interest_rate_type TEXT,
_dim_project_id integer,
_validity_from date,
_validity_to date,
_version integer,
PRIMARY KEY (_tech_id)
);
CREATE INDEX dim_loan_pk_idx ON dim_loan USING btree (_tech_id);
CREATE INDEX dim_loan_compound_idx ON dim_loan USING btree (loan_id, _dim_project_id, _validity_from, _validity_to);
В таблице должна содержать, в конце процесса, около 650K строк. Преобразования начинаются быстро (ish), со скоростью около 1500 строк/сек. Производительность падает со скоростью 50 строк/сек к тому времени, когда таблица имеет около 50 тыс. Строк. запросов, чайник выглядит так:
SELECT _tech_id, _version, "type" AS "Loan Type", interest_rate_type AS int_rate, _validity_from, _validity_to FROM "public".dim_loan WHERE loan_id = $1 AND _dim_project_id = $2 AND $3 >= _validity_from AND $4 < _validity_to
Планировщик запросов оценивает время выполнения 0,1 мс:
"Index Scan using dim_loan_compound_idx on dim_loan (cost=0.42..7.97 rows=1 width=42) (actual time=0.043..0.043 rows=0 loops=1)"
" Index Cond: ((loan_id = 1) AND (_dim_project_id = 2) AND ('2016-01-01'::date >= _validity_from) AND ('2016-01-01'::date < _validity_to))"
"Total runtime: 0.078 ms"
Конечно времена реального исполнения сильно отличаются, около 10мс, что неприемлемо , Включение журнал медленных запросов с auto_explain я вижу с увеличением частоты записи, как это:
Seq Scan on dim_loan (cost=0.00..2354.21 rows=12 width=52)
Filter: (($3 >= _validity_from) AND ($4 < _validity_to) AND (_dim_project_id = $2) AND ((loan_id)::double precision = $1))
< 2016-12-18 21:30:19.859 CET >LOG: duration: 14.260 ms plan:
Query Text: SELECT _tech_id, _version, "type" AS "Loan Type", interest_rate_type AS int_rate, _validity_from, _validity_to FROM "public".dim_loan WHERE loan_id = $1 AND _dim_project_id = $2 AND $3 >= _validity_from
AND $4 < _validity_to
Который не рассказать всю историю в любом случае, поскольку это не только эти запросы, которые выполняются медленно, но все из них. Конечно, я пытался настроить параметры памяти до глупых сумм без реальной разницы в производительности, я также пробовал последние 9.6, которые демонстрировали то же поведение, что и 9,3, что и я использую.
То же преобразование в базе данных MySQL с одинаковыми индексами выполняется с успехом в 5000 строк/с от начала до конца. Я действительно хочу использовать PG, и я уверен, что это нечто тривиальное, но что !? Возможно, что-то с драйвером jdbc? Я проверял, что он все время использует одно соединение, поэтому это даже не проблема с подключением ...
Почему «loan_id» используется для двойной точности? –
место на Ричарде, спасибо! –
Вывод «объяснять анализ» - это ** не ** «расчетное» время выполнения. Это ** фактическое ** время выполнения запроса ** на сервере ** - без отправки результатов клиенту. Если «объяснить анализ» говорит 0.078ms, и вы измеряете 10 мс на стороне клиента, разница - это время, необходимое для отправки данных (хотя это немного удивительно, если возвращены нулевые строки) –