2009-03-19
Text search setup for several languages
There are several ways - below is one common setup.
Assuming you know language, text search setup can be easy. Below is an example for english-russian text collection.
postgres=# create table inttext ( lang regconfig, doc text); CREATE TABLE Time: 760.216 ms postgres=# insert into inttext values('russian','голубые дали'); INSERT 0 1 Time: 365.939 ms postgres=# insert into inttext values('english','hazy distance'); INSERT 0 1 Time: 363.096 ms postgres=# select to_tsvector(lang,doc) from inttext; to_tsvector ---------------------- 'голуб':1 'дал':2 'distanc':2 'hazi':1 (2 rows)
Of course, instead of built-in text search configurations you can use your very own.
Another alternatives are:
2009-03-14
CSV output
Надо было сделать подвыборку не всех полей из большой БД, оказалось очень просто можно сделать так:
psql -t cas -c 'copy ( select id, ra,dec, pm_ra, pm_dec, bmag, vmag, rmag from nomad.main where vmag >= 5 and vmag <=17 ) to stdout with csv' > nomad-x-5-17.csv
2009-03-13
New cool text search features for 8.4+
- We added support of filtering dictionaries Contrary to standard behaviour output from filtering dictionary is always passes to the next dictionary (if any), which allows useful lexeme preprocessing, for example, remove accents without any issues in ts_headline() function.
- unaccent dictionary/function. Uses suffix tree for performance (about 25 times faster than variant with built-in translate() function).
- Add prefix search support to the synonym dictionary. Star sign '*' at the end of definition word indicates, that definition word is a prefix and to_tsquery() function will transform that definition to the prefix search format. Notice, it is ignored in to_tsvector().
> cat $SHAREDIR/tsearch_data/synonym_sample.syn postgres pgsql postgresql pgsql postgre pgsql gogle googl indices index* =# create text search dictionary syn( template=synonym,synonyms='synonym_sample'); =# select ts_lexize('syn','indices'); ts_lexize ----------- {index} (1 row) =# create text search configuration tst ( copy=simple); =# alter text search configuration tst alter mapping for asciiword with syn; =# select to_tsquery('tst','indices'); to_tsquery ------------ 'index':* (1 row) =# select 'indexes are very useful'::tsvector @@ to_tsquery('tst','indices'); ?column? ---------- t (1 row) =# select to_tsvector('tst','indices'); to_tsvector ------------- 'index':1 (1 row)
2009-02-26
Nepali support for text search !
Looks like we (Oleg Bartunov, Teodor Sigaev) did first working patch for nepali language (Devanagari script) support in text search ! We introduced Virama/Halanta support and Spacing Combining category. A lot of Unicode documents readings :)
Thanks to Dibyendra Hyoju and Bal Krishna Bal for testing and valuable discussion !
postgres=# set client_encoding to UTF8; SET Time: 0.119 ms postgres=# select * from ts_parse('default','मदन पुरस्कार पुस्तकालय'); tokid | token -------+--------- 2 | मदन 12 | 2 | पुरस्कार 12 | 2 | पुस्तकालय (5 rows)
'मदन पुरस्कार पुस्तकालय' - Madan Puraskar Pustakalaya, name of an entity
This looks pretty trivial, but actually it was not easy. Below is the the same string, displayed using uniname program. Notice, DEVANAGARI SIGN VIRAMA and DEVANAGARI VOWEL SIGNs, they are listed as punct in locale and should break words, which would be wrong !
character byte UTF-32 encoded as glyph name 0 0 00092E E0 A4 AE म DEVANAGARI LETTER MA 1 3 000926 E0 A4 A6 द DEVANAGARI LETTER DA 2 6 000928 E0 A4 A8 न DEVANAGARI LETTER NA 3 9 000020 20 SPACE 4 10 00092A E0 A4 AA प DEVANAGARI LETTER PA 5 13 000941 E0 A5 81 ु DEVANAGARI VOWEL SIGN U 6 16 000930 E0 A4 B0 र DEVANAGARI LETTER RA 7 19 000938 E0 A4 B8 स DEVANAGARI LETTER SA 8 22 00094D E0 A5 8D ् DEVANAGARI SIGN VIRAMA 9 25 000915 E0 A4 95 क DEVANAGARI LETTER KA 10 28 00093E E0 A4 BE ा DEVANAGARI VOWEL SIGN AA 11 31 000930 E0 A4 B0 र DEVANAGARI LETTER RA 12 34 000020 20 SPACE 13 35 00092A E0 A4 AA प DEVANAGARI LETTER PA 14 38 000941 E0 A5 81 ु DEVANAGARI VOWEL SIGN U 15 41 000938 E0 A4 B8 स DEVANAGARI LETTER SA 16 44 00094D E0 A5 8D ् DEVANAGARI SIGN VIRAMA 17 47 000924 E0 A4 A4 त DEVANAGARI LETTER TA 18 50 000915 E0 A4 95 क DEVANAGARI LETTER KA 19 53 00093E E0 A4 BE ा DEVANAGARI VOWEL SIGN AA 20 56 000932 E0 A4 B2 ल DEVANAGARI LETTER LA 21 59 00092F E0 A4 AF य DEVANAGARI LETTER YA
Next step is to port nepali stemmer, so we can provide default text search configuration for nepali.
Also, we need to improve hunspell support, so nepali ispell dictionaries can be used with text search !
This project is a volunteer work to support PostgreSQL promotion in Nepal (btw, elephants are there). I will visit Nepal this april and will establish more close connections with nepali developers.
2009-02-14
pg_reorg - кластеризация таблицы в онлайне !
Всем известно, что кластеризация таблицы по индексу может дать очень большой выигрыш за счет меньшего количества позиционирования головки диска. Особенно это хорошо для read-only таблиц, для которых раз сделанная кластеризация (clusterdb, CLUSTER …) сохраняет свои хорошие качества. Для изменяющихся данных приходится кластеризовать время от времени, что достаточно мучительно, ибо не только медленно, но и из-за лока на таблицу. И тут рулит pg_reorg, еще одно творение клевых парней из NTT. Вот краткая выжимка из документации
pg_reorg is an utility program to reorganize tables in PostgreSQL databases. Unlike clusterdb, it doesn't block any selections and updates during reorganization. You can choose one of the following methods to reorganize. * Online CLUSTER (ordered by cluster index) * Ordered by specified columns * Online VACUUM FULL (packing rows only) NOTICE: * Only superusers can use the utility. * Target table must have PRIMARY KEY. * You'd better to do ANALYZE after pg_reorg is completed.
И без перевода понятно насколько это полезная утилита ! Узнал про это я из интересной статьи Cluster data, save cash.
2009-01-17
Пик Советов
Наткнулся на страничку калмыка (?) http://www.flat.ru/kalmyk/kazakh/treks/sovet.htm про Пик Советов (4300 м), на который я ходил 2 раза - еще в августе 1986 годах. На этой страничке показан маршрут, которым я с Костей Постновым, Володей Самодуровым, Юрой Шинтарем и Леной Путилиной поднялись на пик Советов, будучи в стройотряде на Алма-Атинской Высокогорной станции ГАИШ, когда пережидали сель, который снес дорогу и наши строительные работы на этом благополучно закончились. Помню, что Акрем обещался наблюдать за нами через Цейсс-600 :) Устали тогда умеренно, разве что обгорели прилично. Вниз спускались очень быстро по сыпуну по очереди, тогда моим чешским вибрамам пришел долгожданный конец. Осталось только несколько слайдов с тех времен.
Второй раз - в 1991 году с Женей Семеновым, Колей Симоновым и его дочерью Дашей (6-7 лет ?). Коля и Даша на вершину не пошли, а я с Семеновым благополучно взобрались по самому кратчайшему маршруту весьма резво, причем я был за оператора и снимал все на камеру Сони (куда жа пленка делась ?), приходилось скакать вверх и вниз, чтобы выбрать хороший план. Кстати, где-то внизу остался Вася Сафрошкин и Кира (другая), почему они не пошли в гору я не помню. Зато прекрасно помню, что в это утро в Москве случился путч и мы с Семеновым прямо на вершине выразили свое негодование (несколько неприличным способом) глядя почему-то на Китай.
Интересно, что никакой горной болезни ни разу ни у кого обнаружено не было, хотя высоту (c 2000 до 4300) набирали за несколько часов. Правда, мы до этого жили на высоте > 2000 м. И на горе Майданак (военной) играли в волейбол на высоте 2700 м, помнится солдаты в оцеплении стояли, чтобы мяч далеко вниз не укатился :) Совсем недавно за пару часов забежали от БТА до вершины горы Пастухова (2700 м), только ноги намочили от ранней росы (вышли в 4 утра). Мне это интересно, так как в апреле я собираюсь в Непал прогуляться вокруг Анапурны (максимум 5400 м), посмотреть на самое высокогорное озеро Тиличо (Tilicho) ( ~5000 м).
2009-01-11
Развитие СУБД PostgreSQL в 2008 году
Олег Бартунов, Федор Сигаев
- GIN - Generalized Inverted Index
- Алгоритм быстрой вставки в обратный индекс - известно, что обновление обратного индекса является "тяжелой" операцией, которая, тем не менее, востребована в задачах оперативного обновления данных. Например, добавление только одной небольшой статьи, которая содержит 100 уникальных слов, вызовет 100 обновлений обратного индекса, что при условии соблюдения целостности и безопасности данных (ACID) является дорогостоящей операцией. Алгоритм предполагает хранение новых записей вне индекса, и добавление их во время работы сборщика статистики (vacuum analyze). При этом выигрыш достигается за счет использования буфера памяти для накапливания обратных списков, которые сбрасываются на диск за один раз по мере заполнения буфера. Стоит отметить, что поиск продолжает работать корректно, но несколько медленнее, из-за необходимости последовательного чтения записей вне индекса. При создании индекса можно указать использовать или нет алгоритм ускоренной вставки.
- Алгоритм поиска на частичное соответствие (partial match). Предыдущие версии обратного индекса GIN поддерживали поиск только по точному совпадению ключей,в то время как новый алгоритм реализует поиск ключей по префиксу.
- Поддержка композитных индексов, т.е. индексов, которые поддерживают комбинацию атрибутов. В PostgreSQL такую поддержку имеют Btree и GiST индексы, однако, эффективность GIN индекса не зависит от того, по какому атрибуту производится поиск, что позволяет использовать один индекс как для поиска по комбинации атрибутов, так и по отдельным атрибутам.
- GiST - Generalized Search Tree
- Поддержка новых версий и исправление ошибок
- Full-text search
- Улучшение поиска с ограничением по весу лексем. Обратный индекс не содержит никаких метаданных, поэтому результаты поиска необходимо проверить на соответствие дополнительным ограничениям, если они были заданы в поисковом запросе. Для этого использовался специальный оператор, который не нес никакой дополнительной семантики и перегружал пользовательский интерфейс. Благодаря улучшениям в ядре PostgreSQL удалось избавиться от лишнего оператора.
- Поддержка префиксного поиска в полнотекстовом поиске с индексной поддержкой GIN. Благодаря поддержке в обратном индексе поиска на частичное соответствие стало возможным использовать в полнотекстовом поиске шаблонов.
- Разработана алгебра полнотекстовых запросов, которая необходима для корректного поиска по фразам (phrase search). В богатый язык запросов полнотекстового поиска (операторы AND, OR, AND NOT, группировка) добавлен оператор, который гарантирует порядок следования операндов и расстояние (в словах) между ними.
- Расширения PostgreSQL
- wildspeed - индексная (GIN) поддержка поиска подстрок для SQL оператора LIKE, например, '%text%'. Эта реализация использует алгоритм поиска на частичное соответствие GIN.
- unaccent - расширение, которое убирает диакритические знаки, используемые во многих европейских языках. Использование суффиксного дерева и кэширования позволило в десятки раз ускорить операцию по сравнению со встроенной функцией translate. Актуальность расширения определяется необходимостью убирать диакритические знаки из текста перед полнотекстовым поиском (индексация и поиск) для получения однозначных результатов.
- btree_gin - реализация B-tree с использованием GIN. Модуль поддерживает практические все основные типы данных, используемые в PostgreSQL и позволяет создавать композитные индексы, так как PostgreSQL не поддерживает создание индексов с использованием разных AM (методов доступа), например, GIN и btree. Наиболее популярный метод доступа - btree поддерживает все основные типы данных, поэтому его эмуляция с помощью GIN, позволяет создавать композитные индексы GIN не только для множеств (для которых GIN и создавался), но и для всех основных типов данных, например, индекс по (timestamp, tsvector) будет ускорять полнотекстовый поиск с ограниченим по дате.
- gevel - добавлена поддержка GIN индексов, быстрая приближенная статистика. Это расширение используется как инструмент для изучения и разработки новых индексов на основе GiST, GIN.
- varbit - индексная поддержка (GiST, GIN) операций (overlap, contains, contained) для типа varbit. Одним из примеров эффективного использования является поиск по флагам, реализованных как тип varbit, для которых стандартный Btree индекс неэффективен из-за малой мощности множества значений (обычно, это 0 или 1).
- pg_trgm - поддержка многобайтных кодировок, в частности, UTF-8. Это расширение реализует поиск похожих строк на основе статистики триграм, а также может использоваться в сочетании с полнотекстовым поиском для поиска с ошибками. Замечательной особенностью этого подхода является независимость от языка.
- ltree - поддержка многобайтных кодировок, в частности, UTF-8. Это расширение используется для индексной поддержки операций с иерархическими данными.
Описанные работы по системам разработки расширений GIN, GiST, полнотекстовому поиску вошли в ядро СУБД PostgreSQL и будут доступны для публичного использования, начиная с версии 8.4, намеченное на первый квартал 2009 года. Большинство расширений также входит в состав дистрибутива PostgreSQL.
Часть результатов была доложена на ежегодной конференции разработчиков PostgreSQL - http://www.pgcon.org/2008/schedule/events/58.en.html, на конференции "Научный сервис в сети Интернет- 2008" http://agora.guru.ru/display.php?conf=abrau2008&page=item011, на конференции "PgDay-2008", Oct 17-18, 2008, Prato, Italy (http://wiki.postgresql.org/wiki/European_PGDay_2008)
2008-12-30
Window function in the CVS HEAD (8.4) !
Window function (SQL 2003) - one of the very interesting for OLAP feature previously missed in PostgreSQL was committed to the CVS HEAD by Tom Lane. Hitoshi Harada wrote proposal and made a patch, see his site for more details. There was no support for user-defined window function, but Tom believe, that 8.4 should have it. Very good.
Simply speaking, window function is an aggregate over a partitioned set of rows. Think about window moving over rows.
One of the interesting application of window function would be data smoothing.
2008-12-19
Toulouse - Lourdes - Gavarnie - St.Jean Pied de Port - Orreaga/Roncesvalles - Biarritz - Toulouse
Weekend at Pyrenees, 860 km driving. The song of Roland, Charlemagne, The Pilgrims Cross, El Camino de Santiago.
No people, no restaurants, no hotels, a lot of cleanest air, whitest snow and romantic. The ocean was stormy, so no swimming, but again, very nice view on waves suddenly appearing in the ocean.
Lourdes was empty, the holy water was freshe, the basilica was nice
Conclusion: Return to Pyrenee at spring/summer time
2008-12-17
Getting words from tsvector
Sometimes it's needed to get indexed words from tsvector. ts_stat() is good, but not convenvient. Function below allows to use ts_stat with tsvector:
CREATE OR REPLACE FUNCTION ts_stat(tsvector, OUT word text, OUT ndoc integer, OUT nentry integer) RETURNS SETOF record AS $$ SELECT ts_stat('SELECT ' || quote_literal( $1::text ) || '::tsvector'); $$ LANGUAGE SQL RETURNS NULL ON NULL INPUT IMMUTABLE;
Then, you can use it
select id, (ts_stat(fts)).* from apod where id=1; id | word | ndoc | nentry ----+------------+------+-------- 1 | 1 | 1 | 1 1 | 2 | 1 | 2 1 | io | 1 | 2 1 | may | 1 | 1 1 | new | 1 | 1 1 | red | 1 | 1 1 | two | 1 | 1 1 | 1979 | 1 | 2 1 | 1996 | 1 | 1 1 | 27th | 1 | 1 1 | also | 1 | 1