Pull to refresh
1
0
Руслан @Ruslan_Y

User

Send message
Здесь это будет нежелательной рекламой.
Ищите на али по «arduino robot kit». Навалом просто.
Руки чешутся добавить ссылку на подкаст с Дмитрием Молдовановым из VAS Experts, где он обстоятельно рассказал где и как используется DPI в современном мире.
Это принципиально разные системы.
Используйте ClickHouse для аналитики, а Tarantool как Key-Value базу.

В том числе, можно использовать и то, и другое.
На примере рекламной сети:

В Tarantool кладёте:
— данные для короткой персонализации;
— данные для таргетинга;
— счётчики для антифрода.

И используете его для запросов непосредственно из крутилки.

В ClickHouse кладёте:
— логи показов рекламы, вместе со всеми данными, свойствами посетителя, факторами;
— логи торгов, аукциона;
— логи кликов;
— постклик данные.

И используете его для построения отчётов:
— для внутреннего использования, для исследований, для оптимизации;
— в сервисе отчётов для клиентов.

Какую СУБД лучше использовать для хранения показаний датчиков и построения графиков по этим данным?

Это зависит от того, что нужно делать с этими датчиками.
Два варианта:
— по определённой логике принимать решение на каждый сигнал или на основе данных за короткое окно времени;
— эффективно хранить все данные и строить графики за любое время.
UFO landed and left these words here
Основное бесиво, это реакция mysql консоли на Ctrl+C, когда хочется начать использовать это :)

psqlrc забыл:
\set QUIET 1
-- formatting
\x auto

\set VERBOSITY verbose
\set ON_ERROR_ROLLBACK interactive
-- show execution times
\timing
-- limit paging
\pset pager off
-- replace nulls
\pset null ¤
\pset linestyle unicode
\pset border 2

-- colorize
--\set PROMPT1 '%[%033[33;1m%]%x%[%033[0m%]%[%033[1m%]%/%[%033[0m%]%R%# '
\set PROMPT1 '%[%033[1m%]%M %n@%/%R%[%033[0m%]%# '
--harolds
--\set PROMPT1 '%[%033[1m%]%M/%/%R%[%033[0m%]%# '
\set PROMPT2 '[more] %R > '



--logging
-- Use a separate history file per-database.
\set HISTFILE ~/.psql_history- :DBNAME
-- If a command is run more than once in a row, only store it once in the
-- history.
\set HISTCONTROL ignoredups

-- Autocomplete keywords (like SELECT) in upper-case, even if you started
-- typing them in lower case.
\set COMP_KEYWORD_CASE upper

-- greeting needs to know where we are
-- \echo '\nWelcome, my magistrate\n'

\set clear '\\! clear;'

--helpful queries
\set uptime 'select now() - backend_start as uptime from pg_stat_activity where pid = pg_backend_pid();'
\set show_slow_queries 'SELECT (total_time / 1000 / 60) as total_minutes, (total_time/calls) as average_time, query FROM pg_stat_statements ORDER BY 1 DESC LIMIT 100;'
\set settings 'select name, setting,unit,context from pg_settings;'
\set conninfo 'select usename, count(*) from pg_stat_activity group by usename;'
\set activity 'select datname, pid, usename, application_name,client_addr, client_hostname, client_port, query, state from pg_stat_activity;'
\set waits 'SELECT pg_stat_activity.pid, pg_stat_activity.query, pg_stat_activity.waiting, now() - pg_stat_activity.query_start AS \"totaltime\", pg_stat_activity.backend_start FROM pg_stat_activity WHERE pg_stat_activity.query !~ \'%IDLE%\'::text AND pg_stat_activity.waiting = true;'
\set dbsize 'SELECT datname, pg_size_pretty(pg_database_size(datname)) db_size FROM pg_database ORDER BY db_size;'
\set tablesize 'SELECT nspname || \'.\' || relname AS \"relation\", pg_size_pretty(pg_relation_size(C.oid)) AS "size" FROM pg_class C LEFT JOIN pg_namespace N ON (N.oid = C.relnamespace) WHERE nspname NOT IN (\'pg_catalog\', \'information_schema\') ORDER BY pg_relation_size(C.oid) DESC LIMIT 40;'
\set uselesscol 'SELECT nspname, relname, attname, typname, (stanullfrac*100)::int AS null_percent, case when stadistinct >= 0 then stadistinct else abs(stadistinct)*reltuples end AS \"distinct\", case 1 when stakind1 then stavalues1 when stakind2 then stavalues2 end AS \"values\" FROM pg_class c JOIN pg_namespace ns ON (ns.oid=relnamespace) JOIN pg_attribute ON (c.oid=attrelid) JOIN pg_type t ON (t.oid=atttypid) JOIN pg_statistic ON (c.oid=starelid AND staattnum=attnum) WHERE nspname NOT LIKE E\'pg\\\\_%\' AND nspname != \'information_schema\' AND relkind=\'r\' AND NOT attisdropped AND attstattarget != 0 AND reltuples >= 100 AND stadistinct BETWEEN 0 AND 1 ORDER BY nspname, relname, attname;'


-- 4 helpful queries from radek http://radek.cc/2009/08/15/psqlrc-tricks-table-sizes/
\set trashindexes '( select s.schemaname as sch, s.relname as rel, s.indexrelname as idx, s.idx_scan as scans, pg_size_pretty(pg_relation_size(s.relid)) as ts, pg_size_pretty(pg_relation_size(s.indexrelid)) as "is" from pg_stat_user_indexes s join pg_index i on i.indexrelid=s.indexrelid left join pg_constraint c on i.indrelid=c.conrelid and array_to_string(i.indkey, '' '') = array_to_string(c.conkey, '' '') where i.indisunique is false and pg_relation_size(s.relid) > 1000000 and s.idx_scan < 100000 and c.confrelid is null order by s.idx_scan asc, pg_relation_size(s.relid) desc );'
\set missingindexes '( select src_table, dst_table, fk_name, pg_size_pretty(s_size) as s_size, pg_size_pretty(d_size) as d_size, d from ( select distinct on (1,2,3,4,5) textin(regclassout(c.conrelid)) as src_table, textin(regclassout(c.confrelid)) as dst_table, c.conname as fk_name, pg_relation_size(c.conrelid) as s_size, pg_relation_size(c.confrelid) as d_size, array_upper(di.indkey::int[], 1) + 1 - array_upper(c.conkey::int[], 1) as d from pg_constraint c left join pg_index di on di.indrelid = c.conrelid and array_to_string(di.indkey, '' '') ~ (''^'' || array_to_string(c.conkey, '' '') || ''( |$)'') join pg_stat_user_tables st on st.relid = c.conrelid where c.contype = ''f'' order by 1,2,3,4,5,6 asc) mfk where mfk.d is distinct from 0 and mfk.s_size > 1000000 order by mfk.s_size desc, mfk.d desc );'
\set rtsize '(select table_schema, table_name, pg_relation_size( quote_ident( table_schema ) || \'.\' || quote_ident( table_name ) ) as size, pg_total_relation_size( quote_ident( table_schema ) || \'.\' || quote_ident( table_name ) ) as total_size  from information_schema.tables where table_type = \'BASE TABLE\' and table_schema not in (\'information_schema\', \'pg_catalog\') order by pg_relation_size( quote_ident( table_schema ) || \'.\' || quote_ident( table_name ) ) desc, table_schema, table_name);'
\set tsize '(select table_schema, table_name, pg_size_pretty(size) as size, pg_size_pretty(total_size) as total_size from (:rtsize) x order by x.size desc, x.total_size desc, table_schema, table_name);'


-- Taken from https://github.com/heroku/heroku-pg-extras
-- via https://github.com/dlamotte/dotfiles/blob/master/psqlrc
\set bloat 'SELECT tablename as table_name, ROUND(CASE WHEN otta=0 THEN 0.0 ELSE sml.relpages/otta::numeric END,1) AS table_bloat, CASE WHEN relpages < otta THEN ''0'' ELSE pg_size_pretty((bs*(sml.relpages-otta)::bigint)::bigint) END AS table_waste, iname as index_name, ROUND(CASE WHEN iotta=0 OR ipages=0 THEN 0.0 ELSE ipages/iotta::numeric END,1) AS index_bloat, CASE WHEN ipages < iotta THEN ''0'' ELSE pg_size_pretty((bs*(ipages-iotta))::bigint) END AS index_waste FROM ( SELECT schemaname, tablename, cc.reltuples, cc.relpages, bs, CEIL((cc.reltuples*((datahdr+ma- (CASE WHEN datahdr%ma=0 THEN ma ELSE datahdr%ma END))+nullhdr2+4))/(bs-20::float)) AS otta, COALESCE(c2.relname,''?'') AS iname, COALESCE(c2.reltuples,0) AS ituples, COALESCE(c2.relpages,0) AS ipages, COALESCE(CEIL((c2.reltuples*(datahdr-12))/(bs-20::float)),0) AS iotta FROM ( SELECT ma,bs,schemaname,tablename, (datawidth+(hdr+ma-(case when hdr%ma=0 THEN ma ELSE hdr%ma END)))::numeric AS datahdr, (maxfracsum*(nullhdr+ma-(case when nullhdr%ma=0 THEN ma ELSE nullhdr%ma END))) AS nullhdr2 FROM ( SELECT schemaname, tablename, hdr, ma, bs, SUM((1-null_frac)*avg_width) AS datawidth, MAX(null_frac) AS maxfracsum, hdr+( SELECT 1+count(*)/8 FROM pg_stats s2 WHERE null_frac<>0 AND s2.schemaname = s.schemaname AND s2.tablename = s.tablename) AS nullhdr FROM pg_stats s, ( SELECT (SELECT current_setting(''block_size'')::numeric) AS bs, CASE WHEN substring(v,12,3) IN (''8.0'',''8.1'',''8.2'') THEN 27 ELSE 23 END AS hdr, CASE WHEN v ~ ''mingw32'' THEN 8 ELSE 4 END AS ma FROM (SELECT version() AS v) AS foo) AS constants GROUP BY 1,2,3,4,5) AS foo) AS rs JOIN pg_class cc ON cc.relname = rs.tablename JOIN pg_namespace nn ON cc.relnamespace = nn.oid AND nn.nspname = rs.schemaname AND nn.nspname <> ''information_schema'' LEFT JOIN pg_index i ON indrelid = cc.oid LEFT JOIN pg_class c2 ON c2.oid = i.indexrelid) AS sml ORDER BY CASE WHEN relpages < otta THEN 0 ELSE bs*(sml.relpages-otta)::bigint END DESC;'
\set blocking 'select bl.pid as blocked_pid, ka.query as blocking_statement, now() - ka.query_start as blocking_duration, kl.pid as blocking_pid, a.query as blocked_statement, now() - a.query_start as blocked_duration from pg_catalog.pg_locks bl join pg_catalog.pg_stat_activity a on bl.pid = a.pid join pg_catalog.pg_locks kl join pg_catalog.pg_stat_activity ka on kl.pid = ka.pid on bl.transactionid = kl.transactionid and bl.pid != kl.pid where not bl.granted;'
\set cache_hit 'SELECT ''index hit rate'' as name, (sum(idx_blks_hit)) / sum(idx_blks_hit + idx_blks_read) as ratio FROM pg_statio_user_indexes union all SELECT ''cache hit rate'' as name, sum(heap_blks_hit) / (sum(heap_blks_hit) + sum(heap_blks_read)) as ratio FROM pg_statio_user_tables;'
\set index_size 'SELECT relname AS name, pg_size_pretty(sum(relpages*1024)) AS size FROM pg_class WHERE reltype=0 GROUP BY relname ORDER BY sum(relpages) DESC;'
\set index_usage 'SELECT relname, CASE idx_scan WHEN 0 THEN ''Insufficient data'' ELSE (100 * idx_scan / (seq_scan + idx_scan))::text END percent_of_times_index_used, n_live_tup rows_in_table FROM pg_stat_user_tables ORDER BY n_live_tup DESC;'
\set index_usage_adv 'SELECT * FROM (SELECT stat.relname AS table, stai.indexrelname AS index, CASE stai.idx_scan WHEN 0 THEN ''Insufficient data'' ELSE (100 * stai.idx_scan / (stat.seq_scan + stai.idx_scan))::text || ''%'' END hit_rate, CASE stat.idx_scan WHEN 0 THEN ''Insufficient data'' ELSE (100 * stat.idx_scan / (stat.seq_scan + stat.idx_scan))::text || ''%'' END all_index_hit_rate, ARRAY(SELECT pg_get_indexdef(idx.indexrelid, k + 1, true) FROM generate_subscripts(idx.indkey, 1) AS k ORDER BY k) AS cols, stat.n_live_tup rows_in_table FROM pg_stat_user_indexes AS stai JOIN pg_stat_user_tables AS stat ON stai.relid = stat.relid JOIN pg_index AS idx ON (idx.indexrelid = stai.indexrelid)) AS sub_inner ORDER BY rows_in_table DESC, hit_rate ASC;'
\set locks 'select pg_stat_activity.pid, pg_class.relname, pg_locks.transactionid, pg_locks.granted, substr(pg_stat_activity.query,1,30) as query_snippet, age(now(),pg_stat_activity.query_start) as "age" from pg_stat_activity,pg_locks left outer join pg_class on (pg_locks.relation = pg_class.oid) where pg_stat_activity.query <> ''<insufficient privilege>'' and pg_locks.pid=pg_stat_activity.pid and pg_locks.mode = ''ExclusiveLock'' order by query_start;'
\set long_running_queries 'SELECT pid, now() - pg_stat_activity.query_start AS duration, query AS query FROM pg_stat_activity WHERE pg_stat_activity.query <> ''''::text AND now() - pg_stat_activity.query_start > interval ''5 minutes'' ORDER BY now() - pg_stat_activity.query_start DESC;'
\set ps 'select pid, application_name as source, age(now(),query_start) as running_for, waiting, query as query from pg_stat_activity where query <> ''<insufficient privilege>'' AND state <> ''idle'' and pid <> pg_backend_pid() order by 3 desc;'
\set seq_scans 'SELECT relname AS name, seq_scan as count FROM pg_stat_user_tables ORDER BY seq_scan DESC;'
\set total_index_size 'SELECT pg_size_pretty(sum(relpages*1024)) AS size FROM pg_class WHERE reltype=0;'
\set unused_indexes 'SELECT schemaname || ''.'' || relname AS table, indexrelname AS index, pg_size_pretty(pg_relation_size(i.indexrelid)) AS index_size, idx_scan as index_scans FROM pg_stat_user_indexes ui JOIN pg_index i ON ui.indexrelid = i.indexrelid WHERE NOT indisunique AND idx_scan < 50 AND pg_relation_size(relid) > 5 * 8192 ORDER BY pg_relation_size(i.indexrelid) / nullif(idx_scan, 0) DESC NULLS FIRST, pg_relation_size(i.indexrelid) DESC;'
\set missing_indexes 'SELECT relname, seq_scan-idx_scan AS too_much_seq, case when seq_scan-idx_scan > 0 THEN ''Missing Index?'' ELSE ''OK'' END, pg_relation_size(relname::regclass) AS rel_size, seq_scan, idx_scan FROM pg_stat_all_tables WHERE schemaname=''public'' AND pg_relation_size(relname::regclass) > 80000 ORDER BY too_much_seq DESC;'

-- Development queries

\set sp 'SHOW search_path;'
\set clear '\\! clear;'
\set ll '\\! ls -lrt;'

\unset QUIET

я довольно подробно изучаю этот вопрос. Вот список возможных вариантов. Кстати, я продолжаю изучать этот вопрос, кому интересно — могу делиться инфой, по мере ихучения приведенных вариантов. Кому интересно — напишите под этим комментом

Собственно, список:

Биржи:
www.toptal.com
www.scalablepath.com
crew.co/how-it-works
gun.io
www.guru.com
mycrowd.com
www.freelancer.com/dashboard
authenticjobs.com
jobspresso.co
remoteok.io

Не биржи, но тоже инструменты, с помощью которых можно найти дистанционную работу:
angel.co
github.com
hubstaff.com/jobs

Исключительно для дизайнеров:
99designs.com
www.crowdspring.com

Что-то непонятное (не изучал):
www.mturk.com
microworkers.com
hourlynerd.com
www.cloudfactory.com
coworks.com
jobbatical.com
remote.co
jobs.remotive.io
weworkremotely.com
hired.com
www.airpair.com
www.topcoder.com
hackerlist.net
x-team.com
www.sofmen.com
UFO landed and left these words here
UFO landed and left these words here
На hexlet отменные курсы по Java двух уровней + дополнительные плюшки в виде открытых уроков. И все это совершенно бесплатно.
Хммм… На продакшене используем SolrCloud — проблем вообще никаких. Фейсеты и прочая агрегативная функциональность в Solr уже достаточно давно. С ElasticSearch не работал, но выглядит как давно прошедший этап для Solr.
А я вот с прошлой работы вам историй принес.

Если вы, PM матерый,
Доработок список длинный
Получили от клиента
До релиза за два дня
Не читай ты и не думай
Допработы там иль баги
Шли скорее программистам
Программисты разберут

А когда бюджет сольется
И начнут искать виновных
Включайте сразу идиота
Идиотов любят все
Скажите что заказчик глупый
Что ленятся программисты
Говнокода понапишут
Не работает продукт
Никогда не признавайте
Что вы вышли из ТЗ
Потому что не читали
Что клиент хотел менять

Ведь ТЗ для идиотов
Программист пусть сам решает
Какие брать ему задачи
Ваше дело — переслать
А когда всем станет ясно
Что вы лишь почтовый прокси
Вас погонят ссаной тряпкой
Нахер вы вообще нужны.
Вот тут есть прекрасный анализ по MNP в разных странах. Лично мое мнение в том, что нужно уходить от номеров в принципе. Я на Наге про это много писал.
До недавнего времени я работал в телеком компании непосредственно с биллингом (тарификацией) и могу сказать что реализацию такого механизма в нормальном виде на настоящий день не представляет ни один специалист с которым я общался на эту тему.

Телеком компании, являющимися по сути посредниками между своими абонентами либо крупными операторами получают от операторов и выдают клиентам тарифы, основанные на разбивке по кодам (иногда по зонам, но это очень редки случай и применяется чаще всего только в работе с физическими и корпоративными клиентами). В этих разбивках с кодами (а коды там, особенно мобильные, могут иметь «степень подробности» до 6-7 знаков после +7) указаны непосредственно тарифы и сроки их действия.

Исходя из предложений операторов, качеств линий и нужд компании отделом маршрутизации строится и настраивается на оборудовании в полу-автоматическом режиме карта маршрутизации телефонного трафика. Это очень точная схема, указывающая по какому коду от какого клиента и какому оператору следует направить звонок. Например «звонок полученный от билайн москва по коду 7926463* направить на мегафон-екатеринбург».

И так работает большинство телекоммуникационных компаний в нашей стране (да и не только)

Что же будет с вводом перехода между сетями с сохранением номера?
Выхода тут обычно видно только два:
1. Вся маршрутизация строится как обычно и счета за звонки выставляются по обычным правилам, а уже сами ОПСОСы, при получении звонка на «ушедшего» от них клиента будут заниматься перенаправлением его на другую сеть и вопросом выплаты/получения за него денег. Естественно это повысит затраты на обслуживание такой сети.

2. Вся эта муть ляжет на плечи телеком компаний — звонки с «ушедшими» клиентами на старую сеть будут просто отбиваться ей а для правильных маршрутов будут существовать некие таблицы переходов доступные где-то. Это СУЩЕСТВЕННО усложнит работу рядовых телекомов, нагрузку на людей и затраты на обслуживание. Ни один из знакомых мне биллингов и средств маршрутизации не поддерживает работу с такими «списками» в каком-то автоматическом режиме, так что сюда надо будет еще приплюсовать затраты на разработку. Кроме того, с ростом числа абонентов будет по экспоненте расти еще и нагрузка на железо, ведь КАЖДЫЙ мобильный звонок нужно будет проверить на соответствие всем этим исключениям.

В общем, я по ходу рад что из телекома пока ушел ) Удачи коллегам… Может будет решено это всё каким-то красивым аккуратным образом (во что верится с трудом)
Мне очень странно читать хвалебные деферамбы этому безусловно популистскому решению здесь, на ресурсе, где общаются большей частью хорошо знакомые с программированием люди.
Для начала я расскажу, как работает на электронной АТС т.н. «анализ номера». Т.е. когда абонент набрал вызываемый номер и передал его с абонентского устройства на коммутатор, главный процессор коммутатора начинает анализировать полученные цифры. Для примера возьмём вариант, когда абонент МТС с кода 916 набирает 8-905-322-2223
8 — префикс выхода из своей номерной зоны. Продолжаем анализ…
9 — мало цифр, продолжаем анализ
0 — мало цифр, продолжаем анализ
5 — «905» — префикс сети Билайн, вызов маршрутизируется на канал связи с оператором Билайн. Анализ прекращён.

Если весь индекс 90х передан Билайну, например, то анализ становиться проще. Если же в 905-ом индексе часть префиксов вынесена, то анализ усложняется — нужно проверять последующие цифры и роутить их в соответствующие каналы.

Этот анализ инженер на электронном коммутаторе прописывает вручную специальными командами. В зависимости от позиции коммунтатора в сети, анализ может быть больше или меньше. Если коммутатор — маршрутный, то анализ будет достаточно простым: эти индексы — сюда, эти индесы — туда… На конечных АТС анализ номера может быть весьма сложным, ибо надо чётко прописывать каждый конечный номер и привязывать его к конкретному абонентскому оборудованию. Но в любом случае, вводить этот анализ номера — самая сложная и трудоёмкая работа на ЭАТС. На совсем современных ЭАТС, может быть, это еще как-то и автоматизировано и как-то визуализировано, но на коммутаторах ранних выпусков это все делается из командной строки вручную.

Вычленить один номер из маршрута на Билайн и перевести его на Мегафон — это означает ацццки усложнить анализ. Ну, один номер — еще ничего. Два, три — тоже терпимо… А если таких номеров надо будет прописывать десятки и сотни — то нужен будет отдельный супер-компьютер для построения корректного анализа номера. Выполнять такую работу человеку просто нереально, ибо ошибок будет неконтролируемо много.
АРХИТЕКТУРА ЭЛЕКТРОННЫХ АВТОМАТИЧЕСКИХ ТЕЛЕФОННЫХ СТАНЦИЙ НЕ ПРЕДНАЗНАЧЕНА для такого «кучерявого» анализа номера. Под «архитектурой» я здесь понимаю совокупность программно-аппаратных средств, ибо «процессор» на ЭАТС — это отдельный модуль со своим количеством РАМ и РОМ, апгрейд которого если и возможен, то только в ограниченном объёме.

И еще, обратите внимание, таким образом «корёжить» анализ при переносе одного номера надо будет не на одном коммутаторе, куда будет приписан номер, А ВООБЩЕ НА ВСЕХ КОММУТАТОРАХ сети.

Я не пытаюсь выгородить хапуг-операторов, но конкретно в данном случае сложность задачи действительно аховая. Если операторов-таки обяжут реализовать эту функциональность, им понадобиться выкидывать и обновлять не какое-то старое коммутационного оборудование на базе реле или шаговых искателей, а вполне себе еще годное электронное. Разумеется, такое внеочередное и внезапное обновление никак не заложено в плане окупаемости инвестиций, т.е. в бизнес-плане, т.е. в текущих тарифах.

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

Мне было бы приятно иметь прямую дорогу до вокзала с постоянно курсирующим по ней каждые 15 минут комфортабельным автобусом, но при этом оплачивать из своего кармана снос уже существующих домов, прокладку новой дороги, закупку автопарка лично меня не прельщает. Я, может быть, воспользуюсь этим путём, а может быть и нет, но денег я должен буду заплатить немедленно, и такая перспектива меня лично совершенно не устраивает.
По сравнению с английским, весьма криво поддерживает, надо сказать.
Приходилось иногда вручную подчищать резльутаты, т.к. некоторые суффиксы им игнорировались начисто.

Пример из кода:
# if adjective
my $stemmer = Lingua::Stem::Snowball->new(lang => $self->{locale}{lang}, encoding => 'UTF-8');
$stemmed = $stemmer->stem($self->{query});
$stemmed =~ s{$_$}{} for qw(ец ск ий); # these are most common suffixes that are not processed by Porter's snowball
UFO landed and left these words here
Уже устал рекламировать Blink вместо родной программы, который и не глючит так, и выглядит прилично, и кросс-платформенный, и с Google-контактами синхронизируется, и вообще =)
Для себя какое-то время назад открыл замечательную книгу — Skiena. The Algorithm Design Manual. Вот в ней об алгоритмах, в частности о графах и эвристиках оптимизации NP задач много, интересно и понятно. Рекомендую.
Скорость работы этой «прослойки» измеряли?
Я делал все то же самое, потом замерил скорость с pgpool и без него.
Получилось что в среднем pgpool ЗАМЕДЛЯЕТ скорость примерно в 3 раза.
В связке pgbouncer-pgpool-postgres проигрыш (!!!) в сравнении с чистым postgres у меня получился 20-30 процентов.
Самая быстрая комбинация — pgbouncer+postgres
На ней я и остановился. У меня pgpool следит за failover-ами и осуществляет репликацию. При failover помимо «дергания» триггера новому мастеру еще назначается выделенный дополнительный IP (у бывшего мастера этот IP удаляется). Все запросы обрабатывает pgbouncer и переадресовывает эти запросы по этому самому выделенному IP.
По поводу листинга скажу больше: в одном случае он реализует UDF функцию для Pig (не лучший выбор), а в другом уже использует шарпы с предоставленной оберткой.
Почему не udf для hive (под хайв они зачастую достаточно короткие)?
Почему не голый MR (для среднего тоже будет элементарно, можно глянуть пример WordCount, в редьюсе посчитать сумму и на выходе отдать деление, а не сумму)?

Но ответ кроется в авторах листинга: M. Isard, Y. Yu, одни из основных разработчиков Dryad, то есть уже показана предвзятость.

Про MPI/GPU vs Dryad/Hadoop сравнение тоже по-моему не совсем корректно, связки GPU+Hadoop потенциально даже применимы, но вот на практике все проекты останавливаются на ресеч и бета стадиях (можно погуглить, несколько полуживых 2-3 летней давности + пару фирм предоставляющих консалтинг без описания use cases), так как сама парадигма map-reduce не очень хорошо вяжется с gpu подходом.

Так же согласен с вами в том, что на данный момент идет сравнение "Dryad мог бы" и "Hadoop и экосистема делает".

Высказывание автора:
И все эти инструменты предоставляют зачастую дублирующиеся решения для задач узкого характера (по сути, обхода ограничений) вместо предоставления единого универсального инструмента решения как парсинга логов, так и подсчета PageRank и анализа графов

Мне тоже режет ухо, так можно на любую вещь сказать, что она предоставляет дублирующий интерфейс:
1. специализированный набор ключей в автомастерской, некоторые дублируют функцию друг друга
2. языки высокого уровня, чем им asm не угодил, ведь предоставляет все необходимые примитивы
3. набор различных фреймворков под разные задачи, пускай в некоторых сферах они и пересекаются

MR & YARN — низкоуровневые примитивы
Pig — императивное описание тасков, работаем со стримом данных
Hive — декларативное, работаем как с sql
Giraph — работа с графовым представлением данных
Storm — event processing, данные обрабатываются еще до сохранения на диск, ациклический граф
Spark — в первую очередь итеративные алгоритмы и машинное обучение, высокая скорость за счет хранения в распределенной таблице в памяти

vs

Dryad & DryadLINQ — абстракция над данными и вычислениями, реализации алгоритмов еще не написаны.

Хотя по поводу 3го пункта с поклонниками ms и c# трудно спорить, так как считают, что есть единственно правильный путь и решение (фреймворк)

За Dryad я наблюдал очень давно, так как альтернативные реализации всегда полезно знать, но все что там было уже давно реализованно в других продуктах, нету только работы через SharedMemory, но по мне это очень спорное решение, уж лучше тогда через pipe работать (что и ожидается в хадупе для обмена данными на одном хосте между task и data нодами). В остальном же, хотели получить достаточно большой комбайн на все случаи жизни, но как и любые попытки обхватить необъятное она провалилась.

p.s. Посмотрел я на этот Naiad и дальше простейшей демки ничего полезного представить они не могут. Опять идет сравнение внутренней разработки и "мы возможно будем делать" с работающей системой для анализа графов.
1

Information

Rating
Does not participate
Location
Нижний Новгород, Нижегородская обл., Россия
Date of birth
Registered
Activity