У меня есть простая таблица в базе данных PostgreSQL 9.0.3, которая содержит данные, опрошенные с контроллера ветряных турбин. Каждая строка представляет значение конкретного датчика в определенное время. В настоящее время в таблице около 90 миллионов строк:
wtdata=> \d integer_data
Table "public.integer_data"
Column | Type | Modifiers
--------+--------------------------+-----------
date | timestamp with time zone | not null
name | character varying(64) | not null
value | integer | not null
Indexes:
"integer_data_pkey" PRIMARY KEY, btree (date, name)
"integer_data_date_idx" btree (date)
"integer_data_name_idx" btree (name)
Один запрос, который мне нужен, это найти время последнего обновления переменной:
select max(date) from integer_data where name = '<name of variable>';
Этот запрос работает нормально при поиске переменной, которая существует в таблице:
wtdata=> select max(date) from integer_data where name = 'STATUS_OF_OUTPUTS_UINT16';
max
------------------------
2011-04-11 02:01:40-05
(1 row)
Однако, если я пытаюсь найти переменную, которой нет в таблице, запрос зависает (или занимает больше времени, чем у меня есть терпение):
select max(date) from integer_data where name = 'Message';
Я позволил запросу выполняться часами, а иногда и днями без конца. В таблице нет строк с именем = 'Сообщение':
wtdata=> select count(*) from integer_data where name = 'Message';
count
-------
0
(1 row)
Я не понимаю, почему один запрос быстрый, а другой - вечный. По какой-то причине запрос вынужден сканировать всю таблицу?
wtdata=> explain select max(date) from integer_data where name = 'Message';
QUERY PLAN
------------------------------------------------------------------------------------------------------------------------
Result (cost=13.67..13.68 rows=1 width=0)
InitPlan 1 (returns $0)
-> Limit (cost=0.00..13.67 rows=1 width=8)
-> Index Scan Backward using integer_data_pkey on integer_data (cost=0.00..6362849.53 rows=465452 width=8)
Index Cond: ((date IS NOT NULL) AND ((name)::text = 'Message'::text))
(5 rows)
Вот план запроса для быстрого запроса:
wtdata=> explain select max(date) from integer_data where name = 'STATUS_OF_OUTPUTS_UINT16';
QUERY PLAN
--------------------------------------------------------------------------------------------------------------------------
Result (cost=4.64..4.65 rows=1 width=0)
InitPlan 1 (returns $0)
-> Limit (cost=0.00..4.64 rows=1 width=8)
-> Index Scan Backward using integer_data_pkey on integer_data (cost=0.00..16988170.38 rows=3659570 width=8)
Index Cond: ((date IS NOT NULL) AND ((name)::text = 'STATUS_OF_OUTPUTS_UINT16'::text))
(5 rows)