4. Что такое Web 2.0?
Для пользователей:
●
collaborative web (UGC, комментарии,
рейтингование и т.д.);
●
веб-приложения, а не веб-сайты
(AJAX, новый уровень интеграции)
●
веб как платформа
(интероперабельность, RSS,
микроформаты и т.д.)
●
закруглённые уголки, отражения в
логотипах и т.д. :-)
___________________
*)
UGC (user-generated content) — контент, созданный пользователями
5. Что такое Web 2.0?
Для разработчиков:
больше больше больше
пользователей разработчиков проектов
больше конкурентов
на рынке
выше темпы высокая пользователи,
растущие
разработки, изменчивость
объёмы хиты, TPS и пр.:
итерации бизнес-
короче требований
данных N = et
Лучшие технологии помогают побеждать!
7. Почему PostgreSQL?
}
1. Производительность,
масштабируемость Качество
2. Надёжность
3. Богатые возможности } Эффективная разработка
}
4. Соответствие стандартам,
“правильность” HR
5. Свобода
8. Как работать с UGC?
1. Таксономия
●
Каталоги
2. Фолксономия
●
Теги
3. Комплексный подход, два пути:
●
Теги + Каталоги
●
И пользователи, и редакторы управляют
каталогами
11. contrib/intarray, contrib/hstore
item
obj_id INT8
item_section_id INT8
item_vendor_id INT8
item_model_id INT8
item_year INT2
item_price NUMERIC(30,6)
item_props intarray
●
Позволяет существенно сэкономить место на диске
●
Производительность хороша, если вы сочетаете GiST и GIN
индексы
●
Иногда разумно кэшировать значения тегов во внешнем
кеше (напр., Memcache; можно применять pgmemcache в
триггерах для инвалидации кэша), если используется
intarray => меньше соединений в SELECT-ах
13. UGC: комплексный подход
Два возможных варианта:
1. Теги + Каталоги
— часто используемый вариант
2. И пользователи, и редакторы контролируют Каталоги
— наиболее перспективный, но сложный для
разработки и поддержки подход
●
UGC-записи каталогов не отображаются в общих списках
выборки <SELECT>, ждут одобрения редакторов.
●
Процедура 'слияния' далеко не простая (как правильно
объединять UGC и редакторский контент?; дубликаты;
синонимы и т.п.).
●
полнотекстовый поиск (стемминг, морфология,
тезаурус), pg_trgm, metaphone, soundex и т.д. могут
помочь. НО: работа человека по-прежнему необходима
14. UGC: подробнее о тегах
1. Используйте FTS (бывший tsearch2) для интеграции
поиска по тегам и текстового поиска:
●
категории FTS, чтобы отличать теги от обычных
слов при поиске (когда необходимо);
●
для обработки тегов можно создать отдельную
конфигурацию FTS.
2. Используйте «префиксный поиск» для поиска по
тегам. Решение пока не тривиально (см. следующие
слайды ;-) )
15. UGC: теги и префиксный поиск
Пример префиксного поиска:
Решение “в лоб” разочаровывает:
test=# EXPLAIN ANALYZE SELECT * FROM tag WHERE tag_name LIKE 'postgr%';
QUERY PLAN
Seq Scan on tag (cost=0.00..6182.75 rows=1 width=105) (actual
time=0.951..102.779 rows=162 loops=1)
Filter: ((tag_name)::text ~~ 'postgr%'::text)
Total runtime: 102.871 ms
(3 rows)
Замечание: ~300 000 уникальных тегов
16. Префиксный поиск: как сделать быстрее
1. Используем text_pattern_ops для ускорения LIKE 'postgr%':
test=# CREATE INDEX i_tag_prefix ON tag
USING btree(lower(tag_name) text_pattern_ops);
CREATE INDEX
test=# EXPLAIN ANALYZE SELECT * FROM tag
WHERE lower(tag_name) LIKE lower('bla%');
QUERY PLAN
Bitmap Heap Scan on tag (cost=43.55..2356.16 rows=1096 width=105)
(actual time=0.164..0.791 rows=235 loops=1)
Filter: (lower((tag_name)::text) ~~ 'postgr%'::text)
> Bitmap Index Scan on i_tag_prefix (cost=0.00..43.28
rows=1096
width=0) (actual time=0.116..0.116 rows=235 loops=1)
Index Cond: ((lower((tag_name)::text) ~>=~ 'bla'::text)
AND
(lower((tag_name)::text) ~<~ 'postgs'::text))
Total runtime: 0.885 ms
17. Префиксный поиск: как сделать быстрее
2. Создаём таблицу tag_words (уникальные теги), чтобы работать
со словами, а не фразами:
CREATE TABLE tag_words AS
SELECT DISTINCT word
FROM ts_stat('SELECT to_tsvector(tag_name) FROM tag'); ждём, ждём
DROP INDEX i_tag_prefix;
CREATE INDEX i_tag_fts ON tag USING gin(to_tsvector(tag_name));
CREATE INDEX i_tag_words_prefix ON tag_words
USING btree(lower(word) text_pattern_ops);
test=# EXPLAIN ANALYZE
SELECT * FROM tag
WHERE to_tsvector('utf8_russian'::regconfig, tag_name::text)
@@ to_tsquery('utf8_russian', '(' || (
SELECT array_to_string(array_accum(lower(word)), '|')
FROM tag_words
WHERE lower(word) LIKE 'postgr%') || ')'); добавляем
'...&word1&word2', если надо
/* план опущен */
Total runtime: 13.243 ms
(11 rows)
18. Комментарии и рейтинги для всего
obj
obj_id INT8 — Не SERIAL, см. следующий слайд
obj_status_did INT8 — Значение из справочника
obj_creator_obj_id INT8 — ID создателя (если применимо)
obj_created TIMESTAMP
obj_modified
obj_commented
TIMESTAMP
TIMESTAMP
}
NOT NULL DEFAULT CURRENT_TIMESTAMP
obj_marks_count INT4
obj_marks_rating FLOAT8 }- оцениваем всё!
obj_tsvector tsvector — Почти везде нужен полнотекст.
user2obj
group
u2o_user_obj_id comment
u2o_obj_obj_id
u2o_mark user comment_author_obj_id
u2o_is_favorite comment_text
19. Комментарии и рейтинги для всего
create table comment (
obj_id INT8 not null default (((nextval('comment_obj_id_seq'::regclass
* 223072849) % (1000000000)::bigint
constraint c_obj_comment_obj_id check
(obj_id between 41000000000 and 41999999999),
comment_author_obj_id INT8,
comment_body VARCHAR (2000) NOT NULL,
constraint PK_MESSAGE primary key (obj_id)
)
inherits (obj);
Как генерируются ID:
nextID = (N mod Y) * X + S,
where X & Y are coprimes, and S is an interval shift
Используем отдельный sequence для каждой таблицы!
не забыть:
SET constraint_exclusion ON;
20. Google Maps mashup: с PostgreSQL
это просто!
Как хранить и индексировать гео-данные в PostgreSQL:
– two integer columns and B-tree
– point column and R-tree
– PostGIS
– pgSphere GiST
– Q3C
21. Итоги
PostgreSQL обладает отличными
возможностями, отвечающими
нуждам Web 2.0 разработчиков
PostgreSQL позволяет разрабатывать
быстро, без потери качества
Создавайте Web 2.0 проекты с PostgreSQL!