2014-10-02 5 views
2

Я попыталсяКак создать составной индекс в Postgres 9

create temp table test (kuupaev date, kellaaeg char(5) ) on commit drop; 
create index on test ((kuupaev||kellaaeg));  

но получил ошибку

ERROR: functions in index expression must be marked IMMUTABLE 

Как этот показатель в Postgres 9?

В Postgres 8 это сработало.

Update

Команды

create temp table test (kuupaev date, kellaaeg char(5) ) on commit drop; 
create index test on test ((kuupaev||kellaaeg));  

в

"PostgreSQL 9.3.4, compiled by Visual C++ build 1600, 32-bit" 

причина ошибки

ERROR: functions in index expression must be marked IMMUTABLE 

но в

"PostgreSQL 8.4.4, compiled by Visual C++ build 1400, 32-bit" 

они работают нормально

+1

Что случилось с 'создать индекс на тест (kuupäev, kellaaeg);' –

+0

мне нужно ускорить запрос, как 'ВЫБРАТЬ макс (kuupäev || kellaaeg) в рес из теста где kuupäev <= date'20140101' и kuupaev || kellaaeg <= '2014010114 23' 'Будет ли ваш индекс ускорять его? – Andrus

+0

Почему бы не использовать столбцы отдельно в предложении 'where'? 'где kuupaev <= дата '2014-01-01' и keellag <'23''. Эта конкатенация на самом деле не имеет смысла. –

ответ

1

Запрос pg_operator показывает, что соответствующая функция реализации оператора anytextcat.

regress=> select l.typname, r.typname, o.oprcode 
      from pg_operator o 
      inner join pg_type l on (o.oprleft = l.oid) 
      inner join pg_type r on (o.oprright = r.oid) 
      where oprname = '||'; 

    typname | typname |  oprcode  
-------------+-------------+----------------- 
anyarray | anyelement | array_append 
anyelement | anyarray | array_prepend 
anyarray | anyarray | array_cat 
text  | text  | textcat 
varbit  | varbit  | bitcat 
bytea  | bytea  | byteacat 
text  | anynonarray | textanycat 
anynonarray | text  | anytextcat 
tsvector | tsvector | tsvector_concat 
tsquery  | tsquery  | tsquery_or 
(10 rows) 

\df+ anytextcat показывает, что это stable (я бегу 9.4beta2 + GIT изменения, но это же обратно до 9.2).

Глядя на соответствующую линию pg_proc.h и git blame ИНГ его, последний коммит был cd30728f, но, глядя на git show показывает, что это не имеет значения. Поэтому я пропускаю его с git blame cd30728f^ -- ./src/include/catalog/pg_proc.h. Работая назад, я вижу, что изменения были следующими:

cd30728f - Allow LEAKPROOF functions for better performance of security views. (9.2) 
3db6524f - Mark some more I/O-conversion-invoking functions as stable not volatile. (9.2) 
8f9fe6ed - Add notion of a "transform function" that can simplify function calls. (9.2) 
c82d931d - Fix the volatility marking of textanycat() and anytextcat() (9.0) 

Из них только c82d931d действительно актуально. 3db6524f изменяет его от изменчивого к стабильному, но это вам не поможет.

git show c82d931d описывает фиксации, что, вероятно, вызванное изменением такое поведение как:

commit c82d931dd180965a9a0c06acc764404f91de8170 
Author: Tom Lane <[email protected]> 
Date: Thu May 27 16:20:11 2010 +0000 

    Fix the volatility marking of textanycat() and anytextcat(): they were marked 
    immutable, but that is wrong in general because the cast from the polymorphic 
    argument to text could be stable or even volatile. Mark them volatile for 
    safety. In the typical case where the cast isn't volatile, the planner will 
    deduce the correct expression volatility after inlining the function, so 
    performance is not lost. The just-committed fix in CREATE INDEX also ensures 
    this won't break any indexing cases that ought to be allowed. 

    Per discussion, I'm not bumping catversion for this change, as it doesn't 
    seem critical enough to force an initdb on beta testers. 

В соответствии с:

git branch --contains c82d931d 

она была введена в выпуске PostgreSQL 9.0.0.

Сообщение о фиксации предполагает, что предположил, что не вызывает никаких проблем с индексами, которые безопасны, а последующее изменение не должно иметь никакого значения.

Однако, присмотревшись, вы не используете text или varchar. Вы используете ужасный старый тип char, который является внутренним bpchar в PostgreSQL.

Проблема здесь будет заключаться в том, что существует тонкое поведение с char, зависящее от локали, или что надзор вызвал это изменение, чтобы не обрабатывать случай для char. Мне нужно будет копать гораздо глубже в источниках, чем у меня есть время на вечер, чтобы быть в курсе, и, откровенно говоря, для типа char(n), на который мне все равно.

Возможно, вы должны использовать только varchar(5). Если вам нужно заполнить пробел, подумайте об этом с помощью lpad.

В противном случае сообщите об этом проблеме pgsql-bugs - но убедитесь, что вы показываете точные версии, от SELECT version().

+0

Я не могу изменить на varchar. Это большое приложение, и такое изменение требует большого количества перезаписи кода. Я обновил вопрос и добавил версии. Как сообщить об ошибке? – Andrus

+0

http://www.postgresql.org/support/submitbug/ ... но ** сначала прочитайте эти инструкции правильно ** или отчет не будет восприниматься всерьез. Вы должны включить ссылку на этот вопрос в отчет, но убедитесь, что отчет сам включает в себя всю необходимую информацию напрямую, не просто скажите «посмотрите на эту ссылку». Используйте слова «регрессия» и «разрыв обратной совместимости», это может привлечь больше внимания. Обратите внимание, что сообщение об ошибке не означает, что что-то произойдет, особенно для несколько неясных вещей, подобных этому; вот что такое http://www.postgresql.org/support/professional_support/. –

+0

Недавно я сообщил об ошибке pg_dump в списке рассылки psql-general, где я участвую, просто написав ему. Том читал это и делал фиксацию. Отчет находится в этом обновлении вопроса. Это нормально? – Andrus

Смежные вопросы