2016-12-18 9 views
1

я бить головой об этом со вчерашнего дня, и я не 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? Я проверял, что он все время использует одно соединение, поэтому это даже не проблема с подключением ...

+0

Почему «loan_id» используется для двойной точности? –

+0

место на Ричарде, спасибо! –

+0

Вывод «объяснять анализ» - это ** не ** «расчетное» время выполнения. Это ** фактическое ** время выполнения запроса ** на сервере ** - без отправки результатов клиенту. Если «объяснить анализ» говорит 0.078ms, и вы измеряете 10 мс на стороне клиента, разница - это время, необходимое для отправки данных (хотя это немного удивительно, если возвращены нулевые строки) –

ответ

2

Только что выяснилось, что причина действительно заключается в том, что кредитный идентификатор дублируется, что, конечно же, делает индекс бесполезным ! Причина - неправильное предположение, сделанное Kettle по метаданным этого столбца, которое исходит из файла excel. Теперь производительность наравне с MySQL! Счастливые дни