Форум: "Прочее";
Текущий архив: 2013.03.22;
Скачать: [xml.tar.bz2];
ВнизADO + Ora = пропихнуть в хранимку blob более 32 кбайт Найти похожие ветки
← →
Es (2012-08-16 16:02) [0]Имеется хранимка на сервере Oracle, один из входящих параметров blob:
...
i_FILE_BODY in blob,
...
Имеем TAdoConnection и TADOStoredProc, натравленный на хранимку.
Тип параметра указан как ftBlob. Грузится как[AddParam].LoadFromStream(..., ftBlob)
При execute получаем ошибку:ORA-01460: затребовано нереализованное или неразумное преобразование
http://www.onlinedisk.ru/get_image.php?id=928134
Что за фигня с ADO? Что он такого делает, что потом ругается ОРАКЛ со СВОЕЙ стороны?
Эксперименты показали, что если сформировать большой блоб на стороне сервера (мегабайт на 15) и запихнуть его в хранимку - то все здорово и беспроблемно. Но если с дельфового клиенту через ADO указанным выше способом - то облом.
Провайдер используется родной: OraOLEDB.Oracle.1 (так как в MS"ном вообще blob не поддерживается).
Клиент Win 7, ора 11g на nix.
Кто-нибудь сталкивался еще с таким бредом?
← →
AV © (2012-08-16 16:16) [1]ага,
переделал через query
oqTmp.sql.text := "Update SUBSCRIBER set PIC=EMPTY_BLOB() Where ID_SUBSCRIBER = :ID_SUBSCRIBER RETURNING PIC INTO :PIC";
oqTmp.ParamByName("PIC").ParamType := ptInput;
oqTmp.ParamByName("PIC").DataType := ftOraBlob;
oqTmp.ParamByName("PIC").AsBLOBLocator.LoadFromFile(dlgOpenPic.FileName);
oqTmp.ParamByName("ID_SUBSCRIBER").asinteger := FSubscriber;
oqTmp.ExecSQL;
← →
QAZ (2012-08-16 16:41) [2]а зачем человеки вообще пихают в базы всякие блобы с картинками ?
почему их не хранить файлами а в базе хранить адрес?
← →
DVM © (2012-08-16 16:43) [3]
> QAZ (16.08.12 16:41) [2]
> а зачем человеки вообще пихают в базы всякие блобы с картинками
> ?
> почему их не хранить файлами а в базе хранить адрес?
удобно потому что
← →
AV © (2012-08-16 16:43) [4]
> QAZ (16.08.12 16:41) [2]
Все в одном, ничего не потеряется
или потеряется все :)
← →
имя (2012-08-16 16:46) [5]Удалено модератором
← →
QAZ (2012-08-16 16:47) [6]а резервировать и тд?
← →
DVM © (2012-08-16 16:47) [7]
> AV © (16.08.12 16:43) [4]
Да кроме этого причин хранить бинарные данные в базе масса, а вот причин не хранить и хранить в файлах я не знаю ни одной.
← →
DVM © (2012-08-16 16:50) [8]Удалено модератором
← →
QAZ (2012-08-16 16:51) [9]
> DVM © (16.08.12 16:47) [7]
ну наверно в базе нужно хранить то что можно искать,сортировать, это ведь основная идея существования баз данных?
а картинку то зачем мучить?
← →
Es (2012-08-16 16:55) [10]Так никто в проблема не разбирался? Что за нафиг делает ADO с блобом при передачи, что у Оры крышу рвет?
← →
DVM © (2012-08-16 16:55) [11]
> QAZ
Из прочих плюсов
1. Разграничение прав на уровне базы.
2. Гораздо легче открыть 1 порт для подключения к базе через интернет, чем городить доступ к файловому серверу и еще как то связывать пути на нем с записями в базе.
3. При хранении файлов отдельно от базы надо заботиться о том, чтобы ссылки всегда были верными и что делать при удалении файла?
Вообще на ibase.ru была статья для опасающихся хранить файлы в базе от создателей Firebird.
← →
QAZ (2012-08-16 16:56) [12]Удалено модератором
← →
AV © (2012-08-16 16:57) [13]
> Что за нафиг делает ADO с блобом при передачи, что у Оры
> крышу рвет?
Есть подозрение, что как -то не так размер передается
Но не разбирался до конца, тупо стал грузить запросом
← →
Sergey Masloff (2012-08-16 16:59) [14]QAZ (16.08.12 16:51) [9]
>ну наверно в базе нужно хранить то что можно искать,сортировать, это >ведь основная идея существования баз данных?
>а картинку то зачем мучить?
Не надо свое видение обобщать. Я лично из своего опыта согласен с DVM (с) и не вижу ни одной причины хнанить связанные данные в разных местах.
DVM © (16.08.12 16:50) [8]
>База же ограничена лишь размером максимального файла в фс.
И даже этим не ограничена.
← →
Sergey Masloff (2012-08-16 17:02) [15]QAZ (16.08.12 16:56) [12]
>нену как сорганизуеш,сдается мне что отображение картинки не самое >важное,и можно потерпеть загрузку при запросе
>даи всякие фрагментации баз за щет ненужной инфы тоже не убыстрят >процесс
Извини но ЯХДР от этого потока сознания ;-)
- что такое "потерять загрузку при запросе"
- про фрагментацию баз вообще достаточно смешно.
← →
DVM © (2012-08-16 17:03) [16]
> QAZ (16.08.12 16:56) [12]
> даи всякие фрагментации баз за щет ненужной инфы тоже не
> убыстрят процесс
Информация в файле базы записывается постранично, при удалении страницы помечаются как свободные, файл базы на диске как правило не уменьшается никогда сам пос себе, может только расти. Т.е фактически запись в базу - это просто запись в файл на диск в свободные страницы. Это по скорости примерно тоже самое что прямо писать в файл. Чуть-чуть медленнее, но самым медленным звеном тут всегда будет диск и сеть, а не сервер баз данных и какие то дополнительные обработки.
← →
QAZ (2012-08-16 17:07) [17]Удалено модератором
← →
DVM © (2012-08-16 17:12) [18]
> QAZ (16.08.12 17:07) [17]
> нуи нахрена нужен файл где половина размера есть неиспользуемое
> место после удалений записей ?
Плата за удобство.
Есть правда один вариант, который я допускаю, но особенно хорошим его все же не считаю. Во многих СУБД можно сделать так (в Firebird например за счет написания своих расширений - udf), чтобы при загрузке файла на сервер баз данных он сохранялся не в базе а рядом с ней в файловой системе. И читался из файловой системы при попытке чтения из базы. Т.е к файлам в файловой системе доступ будет иметь только сервер субд, но прямого доступа извне к ним нет. Но у этого способа есть куча недостатков и они перевешивают единственное "достоинство" - файлы не лежат в базе.
← →
QAZ (2012-08-16 17:14) [19]
> Но у этого способа есть куча недостатков
какие
← →
DVM © (2012-08-16 17:15) [20]
> QAZ (16.08.12 17:07) [17]
> нуи нахрена нужен файл где половина размера есть неиспользуемое
> место после удалений записей ?
Это решаемо кстати на NTFS. Там есть понятие разреженные файлы - файлы которые имеют размер больше чем реально на диске занимают.
← →
AV © (2012-08-16 17:17) [21]имхо, все равно, наверное почти все субд, "форматируют" отведенное им место под себя и пишут данные блоками. Предпочтительно, кратными ФС.
Так что не особо "дырки" будут мешать
← →
QAZ (2012-08-16 17:17) [22]
> DVM © (16.08.12 17:15) [20]
врятли, ведь запись при удалении не зануляется
← →
DVM © (2012-08-16 17:20) [23]
> QAZ (16.08.12 17:17) [22]
> врятли, ведь запись при удалении не зануляется
Ее не надо занулять, достаточно сказать системе, что место от сих до сих (смещение в файле) не используется. Драйвер сам разберется что кому и куда. Я не знаю, использует ли эту возможность хоть одна из существующих субд.
← →
QAZ (2012-08-16 17:24) [24]Удалено модератором
← →
QAZ (2012-08-16 17:26) [25]чувствую что надо изобрести свою СУБД для ленивых батонокидателей дабы спасти,а потом поработить мир
← →
DVM © (2012-08-16 17:26) [26]
> QAZ (16.08.12 17:24) [24]
> далан, и какой функцией?
DeviceIoControl
← →
DVM © (2012-08-16 17:27) [27]
> QAZ
////////////////////////////////////////////////////////////////////////////////
//
// ****************************************************************************
// * Модуль : uNTFSFileStream.pas
// * Назначение : Класс файлового потока, реализующий доп. возможности NTFS
// * Copyright : 2012 © Дмитрий Муратов (dvmuratov@yandex.ru)
// * Версия : 1.0
// * Дата : 06.02.2012
// ****************************************************************************
//
////////////////////////////////////////////////////////////////////////////////
unit uNTFSFileStream;
interface
{$I DEFINES.INC}
{$IFNDEF MSWINDOWS}
These streams are only usable in Windows!!!
{$ENDIF}
{$WARN SYMBOL_PLATFORM OFF}
uses
{$IFDEF DELPHIXE2_UP}
Winapi.Windows, System.SysUtils, System.Classes;
{$ELSE}
Windows, SysUtils, Classes;
{$ENDIF}
type
TNTFSFileStreamOption = (fsoCompressed, fsoSparse, fsoTemporary, fsoEncrypted,
fsoWriteThrough, fsoNoBuffering, fsoRandomAccess, fsoSequentialScan,
fsoDeleteOnClose);
TNTFSFileStreamOptions = set of TNTFSFileStreamOption;
TNTFSFileStream = class(THandleStream)
strict private
FFileName: string;
FMode: Word;
FOptions: TNTFSFileStreamOptions;
procedure SetCompression(const AHandle: THandle; const AEnabled: Boolean);
procedure SetSparse(const AHandle: THandle);
function CreateFile(const AFilename: string; const AMode: Word;
const AOptions: TNTFSFileStreamOptions = []): THandle;
function GetCompressed: Boolean;
procedure SetCompressed(const AValue: Boolean);
public
constructor Create(const AFilename: string; const AMode: Word = fmCreate;
const AOptions: TNTFSFileStreamOptions = []);
destructor Destroy; override;
procedure ZeroData(const AFileOffset: Int64 = 0; const ALength: Int64 = 0);
procedure ZeroDataForTwoOffsets(const AFirstOffset, ALastOffset: Int64);
procedure ZeroToCurrPosition;
property Compressed: Boolean read GetCompressed write SetCompressed;
procedure Recompress;
procedure Decompress;
procedure Compress;
property FileName: string read FFileName;
property Mode: Word read FMode;
property Options: TNTFSFileStreamOptions read FOptions;
end;
← →
DVM © (2012-08-16 17:28) [28]
implementation
resourcestring
rsCanNotEncryptFiles = "Can not encrypt files on a non-NT platform";
rsFileIsNotSparse = "File "%s" is not sparse";
type
TEncryptFile = function(lpFilename: PChar): BOOL; stdcall;
type
TFileZeroDataInformation = record
FileOffset: Int64;
BeyondFinalZero: Int64;
end;
PFileZeroDataInformation = ^TFileZeroDataInformation;
var
EncryptFile: TEncryptFile;
const
FILE_ATTRIBUTE_SPARSE_FILE = $80;
FSCTL_GET_COMPRESSION = $9003C;
FSCTL_SET_COMPRESSION = $9C040;
FSCTL_SET_ZERO_DATA = $980C8;
FSCTL_SET_SPARSE = $900C4;
COMPRESSION_FORMAT_NONE = 0;
COMPRESSION_FORMAT_DEFAULT = 1;
{ TNTFSFileStream }
procedure TNTFSFileStream.Compress;
begin
Compressed := True;
end;
//------------------------------------------------------------------------------
constructor TNTFSFileStream.Create(const AFilename: string;
const AMode: Word = fmCreate; const AOptions: TNTFSFileStreamOptions = []);
begin
FFileName := AFilename;
FMode := AMode;
FOptions := AOptions;
inherited Create(CreateFile(FFilename, FMode, FOptions));
end;
//------------------------------------------------------------------------------
function TNTFSFileStream.CreateFile(const AFilename: string;
const AMode: Word; const AOptions: TNTFSFileStreamOptions): THandle;
var
DesiredAccess: Cardinal;
ShareMode: Cardinal;
CreationDisposition: Cardinal;
FlagsAndAttributes: Cardinal;
Option: TNTFSFileStreamOption;
begin
DesiredAccess := 0;
ShareMode := 0;
if (AMode and fmCreate) = fmCreate then
begin
if FileExists(AFilename) then
if not DeleteFile(AFilename) then
RaiseLastOSError;
DesiredAccess := GENERIC_READ or GENERIC_WRITE;
ShareMode := 0;
CreationDisposition := CREATE_ALWAYS;
FlagsAndAttributes := FILE_ATTRIBUTE_NORMAL;
for Option := Low(TNTFSFileStreamOption) to High(TNTFSFileStreamOption) do
if Option in AOptions then
case Option of
fsoTemporary: FlagsAndAttributes := FlagsAndAttributes or FILE_ATTRIBUTE_TEMPORARY;
fsoWriteThrough: FlagsAndAttributes := FlagsAndAttributes or FILE_FLAG_WRITE_THROUGH;
fsoNoBuffering: FlagsAndAttributes := FlagsAndAttributes or FILE_FLAG_NO_BUFFERING;
fsoRandomAccess: FlagsAndAttributes := FlagsAndAttributes or FILE_FLAG_RANDOM_ACCESS;
fsoSequentialScan: FlagsAndAttributes := FlagsAndAttributes or FILE_FLAG_SEQUENTIAL_SCAN;
fsoDeleteOnClose: FlagsAndAttributes := FlagsAndAttributes or FILE_FLAG_DELETE_ON_CLOSE;
end;
end
else
begin
FlagsAndAttributes := FILE_ATTRIBUTE_NORMAL;
case AMode and 3 of
fmOpenRead: DesiredAccess := GENERIC_READ;
fmOpenWrite: DesiredAccess := GENERIC_WRITE;
fmOpenReadWrite: DesiredAccess := GENERIC_READ or GENERIC_WRITE;
fmOpenReadWrite or fmOpenWrite: DesiredAccess := GENERIC_READ or GENERIC_WRITE;
end;
case AMode and $F0 of
fmShareCompat, fmShareExclusive: DesiredAccess := DesiredAccess or 0;
fmShareDenyWrite: DesiredAccess := DesiredAccess or FILE_SHARE_READ;
fmShareDenyRead: DesiredAccess := DesiredAccess or FILE_SHARE_WRITE;
fmShareDenyNone: DesiredAccess := DesiredAccess or (FILE_SHARE_READ or FILE_SHARE_WRITE);
end;
CreationDisposition := OPEN_EXISTING;
end;
{$IFDEF DELPHIXE2_UP}
Result := Winapi.Windows.CreateFile(PChar(Filename), DesiredAccess,
ShareMode, nil, CreationDisposition, FlagsAndAttributes, 0);
{$ELSE}
Result := Windows.CreateFile(PChar(AFilename), DesiredAccess, ShareMode,
nil, CreationDisposition, FlagsAndAttributes, 0);
{$ENDIF}
if Result = INVALID_HANDLE_VALUE then
RaiseLastOSError;
try
if (AMode and fmCreate) = fmCreate then
begin
if fsoEncrypted in AOptions then
begin
CloseHandle(Result);
if not Assigned(EncryptFile) then
raise Exception.Create(rsCanNotEncryptFiles);
if not EncryptFile(PChar(AFilename)) then
RaiseLastOSError;
Result := CreateFile(AFilename, fmOpenReadWrite or fmShareExclusive, AOptions);
end
else
SetCompression(Result, fsoCompressed in AOptions);
end;
if fsoSparse in AOptions then
SetSparse(Result);
except
CloseHandle(Result);
raise;
end;
end;
← →
DVM © (2012-08-16 17:28) [29]
//------------------------------------------------------------------------------
procedure TNTFSFileStream.Decompress;
begin
Compressed := False;
end;
//------------------------------------------------------------------------------
destructor TNTFSFileStream.Destroy;
begin
if Handle <> 0 then
CloseHandle(Handle);
inherited;
end;
//------------------------------------------------------------------------------
function TNTFSFileStream.GetCompressed: Boolean;
var
CompressionAlgorithm: Word;
Dummy: Cardinal;
begin
if not DeviceIoControl(Handle, FSCTL_GET_COMPRESSION, nil, 0,
@CompressionAlgorithm, SizeOf(CompressionAlgorithm), Dummy, nil) then
RaiseLastOSError;
Result := (CompressionAlgorithm <> COMPRESSION_FORMAT_NONE);
end;
//------------------------------------------------------------------------------
procedure TNTFSFileStream.Recompress;
begin
if Compressed then
begin
Decompress;
Compress;
end;
end;
//------------------------------------------------------------------------------
procedure TNTFSFileStream.SetCompressed(const AValue: Boolean);
begin
if AValue <> GetCompressed then
SetCompression(Handle, AValue);
end;
//------------------------------------------------------------------------------
procedure TNTFSFileStream.SetCompression(const AHandle: THandle;
const AEnabled: Boolean);
var
Dummy : Cardinal;
CompressionAlgorithm : Word;
const
CompressionAlgorithms : array[Boolean] of Word = (
COMPRESSION_FORMAT_NONE,
COMPRESSION_FORMAT_DEFAULT
);
begin
CompressionAlgorithm := CompressionAlgorithms[AEnabled];
if not DeviceIoControl(AHandle, FSCTL_SET_COMPRESSION, @CompressionAlgorithm,
SizeOf(CompressionAlgorithm), nil, 0, Dummy, nil) then
RaiseLastOSError;
end;
//------------------------------------------------------------------------------
procedure TNTFSFileStream.SetSparse(const AHandle: THandle);
var
Dummy : Cardinal;
begin
if not DeviceIoControl(AHandle, FSCTL_SET_SPARSE, nil, 0, nil, 0, Dummy, nil) then
RaiseLastOSError;
end;
//------------------------------------------------------------------------------
procedure TNTFSFileStream.ZeroData(const AFileOffset, ALength: Int64);
begin
ZeroDataForTwoOffsets(AFileOffset, AFileOffset + ALength);
end;
//------------------------------------------------------------------------------
procedure TNTFSFileStream.ZeroDataForTwoOffsets(const AFirstOffset, ALastOffset: Int64);
var
FileZeroDataInformation: TFileZeroDataInformation;
BytesReturned: Cardinal;
begin
if not (fsoSparse in FOptions) then
raise Exception.CreateFmt(rsFileIsNotSparse, [FFileName]);
FileZeroDataInformation.FileOffset := AFirstOffset;
FileZeroDataInformation.BeyondFinalZero := ALastOffset;
if not DeviceIoControl(Handle, FSCTL_SET_ZERO_DATA, @FileZeroDataInformation,
SizeOf(FileZeroDataInformation), nil, 0, BytesReturned, nil) then
RaiseLastOSError;
end;
//------------------------------------------------------------------------------
procedure TNTFSFileStream.ZeroToCurrPosition;
begin
ZeroDataForTwoOffsets(0, Position);
end;
//------------------------------------------------------------------------------
var
ADVAPI32Handle : THandle;
initialization
EncryptFile := nil;
ADVAPI32Handle := LoadLibrary("advapi32.dll");
if ADVAPI32Handle <> 0 then
{$IFDEF UNICODE}
EncryptFile := GetProcAddress(ADVAPI32Handle, "EncryptFileW");
{$ELSE}
EncryptFile := GetProcAddress(ADVAPI32Handle, "EncryptFileA");
{$ENDIF}
finalization
FreeLibrary(ADVAPI32Handle);
EncryptFile := nil;
end.
← →
имя (2012-08-16 17:32) [30]Удалено модератором
← →
имя (2012-08-16 17:35) [31]Удалено модератором
← →
DVM © (2012-08-16 17:36) [32]
> QAZ (16.08.12 17:32) [30]
> одно дело сказать что файл спарседный, а другое дело указать
> место
Смещения можно указать в разреженном файле всегда и какие угодно. Все что между ними будет исключено из файла и места занимать не будет на диске. В чем проблема то?
← →
QAZ (2012-08-16 17:42) [33]
> В чем проблема то?
да все норм,показалось
← →
Es (2012-08-16 19:18) [34]
> согласен с DVM (с) и не вижу ни одной причины хнанить связанные
> данные в разных местах.
Серег, ну вообще в контексте WEB есть одна причина и имя ей - HTTP-протокол, ибо он запрос-ответ ориентированный. Браузер грузит страницу - а там HTTP-ссылки на 20 изображений. Он генерирует еще 20 запросов на получение этих 20 картинок. Самое наглядное, когда используется распространенный вариант front в виде nginx для быстрой отдачи статики, а за ним back в виде apache для обработки динамики.
1) обработка статики:
Клиент / Браузер -> GET/ -> Nginx -> Файловая система, считывание файла и отдача
2) обработка динамики
Клиент / Браузер -> GET/ -> Nginx -> Apache -> PHP -> Database -> blablabla...
В случае хранения картинок в БД первый вариант обработки исключен, а это ооочень сильно снижает быстродействие и не позволяет пользоваться уже считай стандартизированными решениями. Ибо nginx безумно быстро умеет отдавать статический файл с диска, не нагружая Apache инициализацией подключения. Специфика, но очень распространенная, отсюда большая привычка многих начинающих с программирования под веб хранить файлы на диске, а не в БД.
Что в "классическом" программировании вызывает непонимание, тем более это плохо реализуется, по крайней мере при двухзвенной структуре.
← →
MsGuns © (2012-08-17 11:39) [35]Аргументы против файл-серверов:
1) Реляционность. Во многих нормальных КС в базе хранятся не только данные, но и масса непосрественно софта: шаблоны, отчеты, визуальные элементы интерфейса (формы, фрэймы, диалоги, стили и т.д.). Если все это вынести в файлы, получится туча разнокалиберных файлов со сложной системой привязки к собственно логическим объектам модели БД. В самой же базе все связи прекрасно представлены средствами сервера (бизнес-логика).
2) Целостность. Если часть данных модели раположена вне самой БД, то на порядки возрастает сложность ПО по поддержке целостности данных. "Вшивать" в триггеры обращение к внешним файлам - это что-то, да и не всякий скл-сервер позволяет. И что делать с транзакционностью ?
Про бэкапы и ресторы вообще умолчу.
3) Масштабируемость. При резком повышении интенсивности работы (в т.ч. на запись) в файл-серверном варианте обеспечены длительные ожидания и даже зависания, управлять которыми фактически нет возможности. При серверном решении такие возможности имеются, и весьма в ассортименте.
4) Конфеденциальность. Тут все ясно без слов.
Хватит ?
← →
Es (2012-08-17 12:05) [36]Удалено модератором
← →
QAZ (2012-08-17 13:13) [37]а мне кажеца или на серверах где крутятся сотни сайтов и форумов с милиардами файлов, кучей запросов и прочей белеберды, все както работает, с масштабируемостью, конфиденциальностью, бэкапами и тд ?
← →
AV © (2012-08-17 13:20) [38]
> QAZ (17.08.12 13:13) [37]
Разумно..
Но есть подозрение, что это все опять виртуально
Сайт - файл. Внутри твои картинки, скрипты, др. А снаружи это один файл.
У нас так сайт сделан. На одном из серверов виртуалка стоит, бэкап сайта - бэкап файла виртуалки :)
← →
Sergey Masloff (2012-08-17 13:21) [39]QAZ (17.08.12 13:13) [37]
Кажется
← →
QAZ (2012-08-17 13:27) [40]
> AV © (17.08.12 13:20) [38]
кая разница что это снаружи один файл когда внутри тот же милион, да и виртуализация не прибавляет скорости
Страницы: 1 2 вся ветка
Форум: "Прочее";
Текущий архив: 2013.03.22;
Скачать: [xml.tar.bz2];
Память: 0.58 MB
Время: 0.068 c