powered by simpleCommunicator - 2.0.60     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / PostgreSQL [игнор отключен] [закрыт для гостей] / Долгая работа скрипта на plperlu
10 сообщений из 10, страница 1 из 1
Долгая работа скрипта на plperlu
    #35248999
Garik888
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Всем привет.
Есть функция, которая пересылает файл с сервера клиенту. Работает очень хорошо, но на маленьких файлах. Если попробовать переслать файлик размером 100МБ, то все будет висеть очень долго. Есть ли какая нибудь альтернатива этой процедуре или как можно ускорить обработку файла? Спасибо заранее.

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
CREATE OR REPLACE FUNCTION file_read2(text, int4, int4)
RETURNS bytea AS
$BODY$
my $file = @_[ 0 ]; # Имя файла
my $start_pos = @_[ 1 ]; # Смещение от начала
my $length = @_[ 2 ]; # Прочесть кол-во байт

my $f,$s,$v,$ret;
my $c;

$ret = '';
#$c =  0 ;

open($f,"<".$file);
seek($f,$start_pos, 1 );
binmode($f);
while($length >  0 )
{
read($f,$s, 1 );
$v = unpack("C",$s);
if ( ($v>= 0  && $v<= 31 ) || ($v>= 127  && $v<= 255 ) || ($v== 39 ) || ($v== 92 ))
{
my $substr;
$substr = sprintf("%03o",$v);
$ret .= "\\".$substr;
}
else
{
$ret .= $s;
}
$length--;
} # while


close($f);

return ($ret); 

$BODY$
LANGUAGE 'plperlu' VOLATILE;
ALTER FUNCTION file_read2(text, int4, int4) OWNER TO postgres;
...
Рейтинг: 0 / 0
Долгая работа скрипта на plperlu
    #35249895
Фотография Степан H.
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Скорее всего plperlu и все процедура тут ни при чем, т.к. раньше тоже пробовал сохранять данные в bytea а потом доставать их с помощью ZEOS (DELPHI) - метод другой а скорость очень низкая.

А что именно создает такую нагрузку ? Возможно горомное количество маленьких I/O
Если данные передаются через PostgreSQL, стало быть буфер очень маленький, а увеличивать еще не было смысла ...

Проблему решил методом прокидки файла на клиент через FTP (благо, условия безопасности позволяют)
...
Рейтинг: 0 / 0
Долгая работа скрипта на plperlu
    #35249908
Фотография Ёш
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
а если через large objects ? может быть быстрее будет.

на сервере под админом, создаём функцию что бы обычный пользователь мог загружать файлы в базу, допустим:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
--- проверки корректности имени файла не забыть сделать
--- например заменить file_name text на file_name sane_file_name_domain
--- а в ограничениях домена sane_file_name_domain - проверять корректность имени файла
create function cache_file(key text, file_name text, OUT r oid)
as $$begin
insert into files_cache values ($ 1 , lo_import($ 2 )) returning o into r;
end$$ language plpgsql
security definer;

files_cache например так:
Код: plaintext
create table files_cache (key text, o oid); 

теперь клиент через
Код: plaintext
select cache_file('какой-то ключ', 'путь к файлу');
может загружать файл на сервере в базу. на клиенте например через клиентскую версию функции lo_export выгружать файл из базы на локальный диск. oid файла брать из files_cache с соответствующим ключём. как конкретно вызывать lo_export клиентский - зависит от языка, например из php :
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
<?php
   header('Content-type: image/jpeg');
   $image_oid =  189762345 ;
   $database = pg_connect("dbname=jacarta");
   pg_query($database, "begin");
   $handle = pg_lo_open($database, $image_oid, "r");
   pg_lo_read_all($handle);
   pg_query($database, "commit");
?>
читает из базы large object с oid 189762345 и вываливает его в браузер =)
выгружать сразу всё в локальный файл через lo_export необязательно, lo предоставляет интерфейс похожий на файловый: открытие, позиционирование, чтение блока, запись блока, закрытие. работа с lo_ должна производиться внутри транзакции.

ps: у меня так отчёты работают, в качестве ключа я использую md5 сумму шаблона отчёта с данными.

описание клиентских функций из libpq


--
„Истина — это вовсе не то, что можно убедительно доказать, это то, что
делает всё проще и понятнее“ — Антуан де Сент-Экзюпери
...
Рейтинг: 0 / 0
Долгая работа скрипта на plperlu
    #35249910
Фотография Ёш
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
выгода здесь может быть в том, что, насколько я понимаю, large objects НЕ конвертируются в текстовое представление (типа Вашего $substr = sprintf("%03o",$v); $ret .= "\\".$substr;) при работе с ними, соответственно имхо должно быть быстрее.


--
„Истина — это вовсе не то, что можно убедительно доказать, это то, что
делает всё проще и понятнее“ — Антуан де Сент-Экзюпери
...
Рейтинг: 0 / 0
Долгая работа скрипта на plperlu
    #35249932
Фотография Степан H.
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
В очередной раз, Ёш большое спасибо.
...
Рейтинг: 0 / 0
Долгая работа скрипта на plperlu
    #35250221
Serik Akhmetov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Garik888Всем привет.
Есть функция, которая пересылает файл с сервера клиенту. Работает очень хорошо, но на маленьких файлах. Если попробовать переслать файлик размером 100МБ, то все будет висеть очень долго. Есть ли какая нибудь альтернатива этой процедуре или как можно ускорить обработку файла? Спасибо заранее.
Как вы вызываете эту функцию ? Я надеюсь вы не читаете за один раз все 100 Мб ?

Могу предположить, что одной из причин медленной работы может быть
Код: plaintext
read($f,$s, 1 );
1 байтовое чтение, если читать из файла сразу блок нужного размера, должно быть быстрее.
Если будете использовать метод Ёш , напишите, насколько стало быстрее.
...
Рейтинг: 0 / 0
Долгая работа скрипта на plperlu
    #35250562
Garik888
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Ёша если через large objects ? может быть быстрее будет.

на сервере под админом, создаём функцию что бы обычный пользователь мог загружать файлы в базу, допустим:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
--- проверки корректности имени файла не забыть сделать
--- например заменить file_name text на file_name sane_file_name_domain
--- а в ограничениях домена sane_file_name_domain - проверять корректность имени файла
create function cache_file(key text, file_name text, OUT r oid)
as $$begin
insert into files_cache values ($ 1 , lo_import($ 2 )) returning o into r;
end$$ language plpgsql
security definer;

files_cache например так:
Код: plaintext
create table files_cache (key text, o oid); 

теперь клиент через
Код: plaintext
select cache_file('какой-то ключ', 'путь к файлу');
может загружать файл на сервере в базу. на клиенте например через клиентскую версию функции lo_export выгружать файл из базы на локальный диск. oid файла брать из files_cache с соответствующим ключём. как конкретно вызывать lo_export клиентский - зависит от языка, например из php :
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
<?php
   header('Content-type: image/jpeg');
   $image_oid =  189762345 ;
   $database = pg_connect("dbname=jacarta");
   pg_query($database, "begin");
   $handle = pg_lo_open($database, $image_oid, "r");
   pg_lo_read_all($handle);
   pg_query($database, "commit");
?>
читает из базы large object с oid 189762345 и вываливает его в браузер =)
выгружать сразу всё в локальный файл через lo_export необязательно, lo предоставляет интерфейс похожий на файловый: открытие, позиционирование, чтение блока, запись блока, закрытие. работа с lo_ должна производиться внутри транзакции.

ps: у меня так отчёты работают, в качестве ключа я использую md5 сумму шаблона отчёта с данными.

описание клиентских функций из libpq


--
„Истина — это вовсе не то, что можно убедительно доказать, это то, что
делает всё проще и понятнее“ — Антуан де Сент-Экзюпери


Но ведь в этом варианте файл храниться в базе, а как сделать что бы файл лежал в файловой системе.
...
Рейтинг: 0 / 0
Долгая работа скрипта на plperlu
    #35250574
Garik888
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Ёш
Код: plaintext
select cache_file('какой-то ключ', 'путь к файлу');
может загружать файл на сервере в базу. на клиенте например через клиентскую версию функции lo_export выгружать файл из базы на локальный диск. oid файла брать из files_cache с соответствующим ключём. как конкретно вызывать lo_export клиентский - зависит от языка, например из php :
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
<?php
   header('Content-type: image/jpeg');
   $image_oid =  189762345 ;
   $database = pg_connect("dbname=jacarta");
   pg_query($database, "begin");
   $handle = pg_lo_open($database, $image_oid, "r");
   pg_lo_read_all($handle);
   pg_query($database, "commit");
?>
читает из базы large object с oid 189762345 и вываливает его в браузер =)
выгружать сразу всё в локальный файл через lo_export необязательно, lo предоставляет интерфейс похожий на файловый: открытие, позиционирование, чтение блока, запись блока, закрытие. работа с lo_ должна производиться внутри транзакции.

ps: у меня так отчёты работают, в качестве ключа я использую md5 сумму шаблона отчёта с данными.

описание клиентских функций из libpq


--
„Истина — это вовсе не то, что можно убедительно доказать, это то, что
делает всё проще и понятнее“ — Антуан де Сент-Экзюпери


Что то смутно как то на php, ничего не понятно. Нет ли примера на Delphi с использованием Zeos компонента??
...
Рейтинг: 0 / 0
Долгая работа скрипта на plperlu
    #35250970
Фотография Степан H.
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Garik888
.....
Что то смутно как то на php, ничего не понятно. Нет ли примера на Delphi с использованием Zeos компонента??

так ведь если юзать ZEOS то файл тоже находится в базе

Delphi
Код: plaintext
 ZEOSQueryfilebody.SaveToFile('C:\myfile.doc');

Для малого объема сойдет, но для 100 метров тормозить будет по любому.
...
Рейтинг: 0 / 0
Долгая работа скрипта на plperlu
    #35253910
Фотография Ёш
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Garik888Но ведь в этом варианте файл храниться в базе, а как сделать что бы файл лежал в файловой системе.я только основную идею написал, а реализовать можно как угодно, что например Вам мешает воспринимать базу как кэш в который заливаются файлы только для того что бы передать их клиенту ? :)
такой вариант например: сделайте ключ для LO из двух полей, первое - полное имя файла, второе - дата его создания/модификации + размер. функцию cache_file сделать чуть интеллектуальнее, что бы она перед загрузкой в базу проверяла, есть ли уже в базе такой файл, и совпадает ли его дата создания/модификации + размер с тем что в файловой системе. если совпадает - возвращаем из базы, если нет - очищаем LO и загружаем из файловой системы снова. что бы в базе не висели LO к которым уже никогда никто не захочет получить доступ - можно раз в сутки запускать скрипт который будет например проверять - есть ли в файловой системе файл лежащий в базе, если нету - удалять его из кэша.
...
Рейтинг: 0 / 0
10 сообщений из 10, страница 1 из 1
Форумы / PostgreSQL [игнор отключен] [закрыт для гостей] / Долгая работа скрипта на plperlu
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]