Master-X
Форум | Новости | Статьи
Главная » Форум » Tube сайты » 
Тема: Импорт базы
цитата
26/03/17 в 06:43
 relativity_media
Всех приветствую!
Больше вопрос наверное о том как сохранять свою базу в актуальном состоянии, минимизировать абузы и при этом не обламывая клиента, доставлять контент оперативно и без всяких "Video not found".
Вобщем вот структура базы моего движка, ну это что касается видео контента и все что с ним связано, тумбы, теги:

А действия такие, вначале из *.csv файла копируются данные во временную таблицу, а потом с этой таблицы раскидываются по связным целевым таблицам, вот если взять к примеру шаблон дампа из xhamster.com:
<id>|<embed_url>|<title>|<duration>|<date_added>|<thumb1>;<thumb2>;<thumb3>|<tag1>;<tag2>;<tag3>
Здесь проблема в тумбах и тегах, потому как нужно взять строку сплитануть ее по символу ";" в массив, потом этот массив добавить в тумбы теги таблицы соответственно. Сам импорт во временную таблицу проходит за короткое время, но расфасовка по таблицам занимает кучу времени. На моем стареньком буке 90К импортировалось примерно 10 минут. Аможет оставить все как есть без нормализации данных, то есть тупо одна таблица с соотв. полями, импорт будет легкий но зато потом проблема будет с доступом данных, к примеру нужно взять все видосы по какому нибудь определенному тегу или по двум.
Более гибкий redtube.com как мне кажется, со своим XML-RPC, плюс еще можно чекать каждый видос на актуальность, вот если бы хомяк открыл апи для доступа к данным было бы вообще шоколадно.
Еще хотел спросить - каков интервал апдейта базы у хомяка?, а то я уже 2 письма с вопросами в фидбэк отправил и молчок.
цитата
26/03/17 в 13:43
 dizziness
relativity_media писал:
Сам импорт во временную таблицу проходит за короткое время, но расфасовка по таблицам занимает кучу времени. На моем стареньком буке 90К импортировалось примерно 10 минут.


Наверняка ты там нагородил ужаснейший sql запрос, показал бы. и зачем промежуточная таблица нужна?

А ускорить пачку инсертов, можно через транзакции, например.


relativity_media писал:

Аможет оставить все как есть без нормализации данных, то есть тупо одна таблица с соотв. полями, импорт будет легкий но зато потом проблема будет с доступом данных, к примеру нужно взять все видосы по какому нибудь определенному тегу или по двум.


Почему проблема?
цитата
26/03/17 в 18:15
 relativity_media
dizziness писал:
Наверняка ты там нагородил ужаснейший sql запрос

Это верно, элегантностью мой код не может похвастаться )). Если конкретно это постгрес с хранимыми процедурами, могу запостить код если плохо не станет :)
Код:

drop function if exists prepare_tube_record(varchar) cascade;
drop function if exists insert_thumbs(integer, varchar) cascade;
drop function if exists insert_tags(integer, varchar) cascade;
drop function if exists import_data() cascade;
drop type if exists tube_struct_table cascade;

-- delete from video;

create temporary table if not exists data_csv (
   id integer,
   embed_url varchar,
   title varchar,
   duration varchar,
   date_added varchar,
   thumbs varchar,
   tags varchar
);

copy data_csv from 'C:/Users/.../example.csv' with (
   delimiter '|'
);

create type tube_struct_table as (
   domain varchar,
   embed_format_url varchar
);


create function prepare_tube_record(url varchar) returns tube_struct_table as $$
declare format varchar;
declare tube_rec tube_struct_table;
begin
   -- format: http://xhamster.com/xembed.php?video=217
   tube_rec.domain := (select regexp_matches(url, E'(https?:)?\/\/(www\.)?([^\/]+)'))[3];
   format := regexp_replace(url, E'//[^\/]+', '//<DOMAIN>');
   tube_rec.embed_format_url := regexp_replace(format, E'=[0-9]+$', '=<ID>');
   return tube_rec;
end;
$$ language 'plpgsql';


create function insert_thumbs(_video_id integer, thumbs varchar) returns unknown as $$
declare thumbs_arr varchar array;
begin
   thumbs_arr := regexp_split_to_array(thumbs, E';');
   insert into thumb (thumb_url, video_id) select unnest(thumbs_arr), _video_id;
   return 'thumbs are loaded.';
end;
$$ language 'plpgsql';

create function insert_tags(_video_id integer, tags varchar) returns varchar as $$
declare tags_arr varchar[] = regexp_split_to_array(tags, E';');
declare result record;
begin
   insert into tag (tag_name) (select distinct a.a from unnest(tags_arr) a left join tag b
      on a.a = b.tag_name where b.tag_name is null);

   insert into vid_tag_rel (tag_id, video_id) select distinct b.id, _video_id
      from unnest(tags_arr) a left join tag b on a.a = b.tag_name;
   return 'tags are loaded.';
end;
$$ language 'plpgsql';


CREATE FUNCTION import_data() RETURNS varchar AS $$
declare _row record;
declare tube_rec tube_struct_table;
declare _tube_id integer;
declare _video_id integer;
declare cnt integer;
BEGIN
   cnt := 0;
   for _row in select * from data_csv loop
      cnt := cnt + 1;
      -- insert in tube table
      tube_rec := prepare_tube_record(_row.embed_url);
      select id from tube into _tube_id where domain = tube_rec.domain;
      if _tube_id is null then
         insert into tube (domain, embed_format_url) values ((tube_rec).*) returning id into _tube_id;
      end if;

      -- insert in video table
      select id from video into _video_id where tube_id = _tube_id and embed_key = cast(_row.id as varchar);
      if _video_id is null then
         insert into video (title, duration, date_added, embed_key, tube_id) values (
            _row.title,
            _row.duration,
            to_timestamp(_row.date_added, 'YYYY-MM-DD'),
            cast(_row.id as varchar),
            _tube_id
         ) returning id into _video_id;

         --insert thumbs
         perform insert_thumbs(_video_id, _row.thumbs);

         --insert
         perform insert_tags(_video_id, _row.tags);
      end if;
      raise notice 'Val: %', cnt;
   end loop;
   return 'successfull.';
END;
$$ LANGUAGE 'plpgsql';

select import_data();

Потом пробовал с триггерами переписать этот код, производительность не изменилась. Сейчас думаю разбить задачу на процессы, чтобы каждый процесс запускал этот "скрипт" со своим диапазоном айдишников ну чтобы побыстрее было, опять же надо продумать блокировку либо на уровне базы либо приложения, во избежании одновременной записи или выборки.
Всмысле, а насчет варианта "как есть", как думаешь это возможно, этоже столько данных надо перелопатить базе что бы сделать выборку по тегам например, это ладно 90К строк пока что, а если база подрастет до 1М?
Насчет транзакции, еще пока плохо понимаю этот механизм, но обязательно рассмотрю этот вариант, спасибо за наводку!
цитата
26/03/17 в 18:31
 relativity_media
dizziness писал:
и зачем промежуточная таблица нужна?

А так удобнее манипулировать данными, во время написания этого plpgsql скрипта иногда заглядывал туда тестировал некоторые запросы, к тому же она временная.
цитата
26/03/17 в 20:02
 dizziness
relativity_media:

постгресом никогда не пользовался(хотя пора давно начать), там вроде от настроек самого постгреса много чего зависит.


как то так попробуй.

Код:

BEGIN TRANSACTION; SELECT import_data(); COMMIT;


Эта страница в полной версии