The OpenNET Project / Index page

[ новости /+++ | форум | теги | ]

MySQL и хранение картинок в базе (mysql image binary php sql)


<< Предыдущая ИНДЕКС Поиск в статьях src Установить закладку Перейти на закладку Следующая >>
Ключевые слова: mysql, image, binary, php, sql,  (найти похожие документы)
Date: Thu, 04 Jul 2002 16:44:53 +0600 From: Nickolay Kondrashov <[email protected]> Newsgroups: fido7.su.dbms.sql Subject: MySQL и хранение картинок в базе > Прошу совета как быть по быстродействию обработки базы ... > Суть: создаю галерею картинок .. связка php + mysql + apache .. > Т.е. надо хранить картинки! Я вот думаю где их лучьше хранить: в базе или на > диске как отдельное файло? Интересует вопрос по быстродействию ... > > Т.Е. что будет быстрее обрабатываться: база в которой картинки храняться, или > база в которой хранятся ссылки на картинки (url тобишь ..)? > P.S. учитываю что картинок будет больше 300mb в jpg`ах ... У этих двух подходов есть свои плюсы и минусы. Попробую их перечислить. Значит, хранение в БД. + Файлы проекта хранятся централизовано (что особенно хорошо при командной разработке). + Доступ к файлам в любом случае будет осуществляться через скрипт-загрузчик, что дает возможность более гибко контролировать этот процесс. - Доставка файла скриптом из БД будет с большей вероятностью проходить медленнее чем апачем из файловой системы. - В целом дамп БД будет слишком большим и, возможно, репликация будет требовать широких каналов между удаленными серверами. Также такой дамп будет трудно читаем по F3, т.к. бинарные данные будут смешаны с другими данными. Решается настройкой репликации и продумыванием структуры БД, т.е. нужно все бинарные данные засунуть в несколько таблиц (в твоем случае только не в одну). Сделай так чтобы, например, таблица MyBinariesXXX создавалась, когда в кол-во записей в таблице MyBinaries(XXX-1) превысило знчение YYY. Hапиши классик, который инкапсулировал бы доступ к этим разбросанным данным как к одной куче. Тогда MySQL будет шарить по этим таблицам почти также быстро как и апач по файловой системе и 300М ему будет не помеха. В этом же случае дамп БД будет легко читаем, т.к. бинарные данные расположены в специализированных таблицах. Хранение в файловой системе. + Высокая скорость доступа и меньшая нагрузка на сервер. Hекоторые товарищи, говорили, что выигрыш в скорости значителен, если количество файлов в папке не превышает порядка нескольких тысяч. Эту цифру, конечно, можно узнать получше, если реализовать схему подбную той, что описывалась выше, только не с таблицами а с папками. - Проблемы с целостностью данных, т.е. синхронизацией БД и файловой системы. Такие проблемы часто возникают если над проектом работает несколько разработчиков. Вывод: Оба подхода имеют право на существование при условии грамотной реализации доступа к данным и организации самих данных. Обычно я предпочитаю первый подход, т.к. объем данных и проигрыш в быстродействии незначительны. А указанные плюсы очень важны. Вот пример реализации универсального интерфейса доступа к бинарным данным. Используемые библиотеки: PHPlib для доступа к БД, PEAR для протоколирования. СУБД - MySQL. ______________________________ схема ______________________________ create table binaries ( id int(14) auto_increment not null, bin_data mediumblob, mime_type varchar(100), primary key (id) ); ______________________________ lib/binlib/BinariesIO.php - класс инкапсулирующий доступ к данным ______________________________ <?php class BinariesIO { var $mConfig; var $mDb; function BinariesIO(&$config, &$db) { $this->mConfig=&$config; $this->mDb=&$db; $GLOBALS["gAppLog"]->log("bin_folder: ".$this->mConfig["BINARIES_FOLDER"]); $GLOBALS["gAppLog"]->log("binscript_uri: ".$this->mConfig["BINSCRIPT_URI"]); if(!file_exists($this->mConfig["BINARIES_FOLDER"])) { $GLOBALS["gAppLog"]->log("bin_folder is not exist"); mkdir($this->mConfig["BINARIES_FOLDER"],0777); } } function IsExists($id) { $GLOBALS["gAppLog"]->log("IsExists('".$id."')"); $sql="SELECT id, mime_type FROM binaries WHERE id='$id'"; $this->mDb->query($sql); return $this->mDb->next_record(); } function &GetBinaryObject($id) { $GLOBALS["gAppLog"]->log("GetBinaryObject('".$id."')"); $sql="SELECT id, mime_type FROM binaries WHERE id='$id'"; $this->mDb->query($sql); $bo=&new BinaryObject($this); if($this->mDb->next_record()) { $bo->mId=$this->mDb->f("id"); $bo->mMimeType=$this->mDb->f("mime_type"); } else { return null; } return $bo; } function &CreateBinaryObject() { $GLOBALS["gAppLog"]->log("CreateBinaryObject()"); $sql="INSERT INTO binaries (mime_type, bin_data) VALUES(NULL,NULL)"; $this->mDb->query($sql); $sql="SELECT MAX(id) from binaries"; $this->mDb->query($sql); $this->mDb->next_record(); $bo=new BinaryObject($this); $bo->mId=$this->mDb->f(0); return $bo; } function &RemoveBinaryObject($id) { $bo=$this->GetBinaryObject($id); if($bo==null) return; $path=$bo->GetPath(); if($path!=null) if(file_exists($path)) unlink($path); $sql="DELETE FROM binaries WHERE id='$id'"; $this->mDb->query($sql); } function &GetBinaryObjectList() { $GLOBALS["gAppLog"]->log("GetBinaryObjectsList()"); $sql="SELECT id, mime_type FROM binaries"; $this->mDb->query($sql); for($i=0;$this->mDb->next_record();$i++) { $bo=&new BinaryObject($this); $bo->mId=$this->mDb->f("id"); $bo->mMimeType=$this->mDb->f("mime_type"); $boList[$i]=$bo; } return $boList; } } class BinaryObject { var $mId; var $mMimeType; var $mBio; function BinaryObject(&$bio) { $this->mBio=&$bio; } function GetAccessUrl() { return $this->mBio->mConfig["BINSCRIPT_URI"]."?id=".$this->mId; } function GetPath() { return $this->mBio->mConfig["BINARIES_FOLDER"]."/".$this->mId.".bin"; } function SetData(&$data) { $GLOBALS["gAppLog"]->log("SetData(data)"); if($this->IsFile()) { $h=fopen($this->GetPath(), "w"); fwrite($h,&$data,strlen(&$data)); fclose($h); } else { $sql="UPDATE binaries SET bin_data='".addslashes($data)."'"; $this->mBio->mDb->query(&$sql); } } function &GetData() { $GLOBALS["gAppLog"]->log("GetData()"); if($this->IsFile()) { $GLOBALS["gAppLog"]->log("loading from '".$this->GetPath()."' size=".filesize($this->GetPath())); $h=fopen($this->GetPath(), "r"); $data=&fread($h,filesize($this->GetPath())); fclose($h); return ($data); } else { $GLOBALS["gAppLog"]->log("loading from binaries db"); $sql="SELECT bin_data FROM binaries WHERE bin_data IS NOT NULL AND id='".$this->mId."'"; $this->mBio->mDb->query($sql); if($this->mBio->mDb->next_record()) { return ($this->mBio->mDb->f("bin_data")); } else { return null; } } } function SetDataFromMultipartRequest($fieldName) { $GLOBALS["gAppLog"]->log("SetDataFromMultipartRequest('".$fieldName."')"); if($fieldName=="none") return; $h=fopen($fieldName,"r"); $data=&fread($h,filesize($fieldName)); fclose($h); if($this->IsFile()) { $h=fopen($this->GetPath(), "w"); fwrite($h,&$data,strlen(&$data)); fclose($h); } else { $sql="UPDATE binaries SET bin_data='".addslashes($data)."' WHERE id='".$this->mId."'"; $this->mBio->mDb->query(&$sql); } } function GetMimeType() { $GLOBALS["gAppLog"]->log("GetMimeType()"); $sql="SELECT mime_type FROM binaries WHERE id='".$this->mId."'"; $this->mBio->mDb->query($sql); if($this->mBio->mDb->next_record()) { return stripslashes($this->mBio->mDb->f("mime_type")); } else { return null; } } function SetMimeType($mimeType) { $GLOBALS["gAppLog"]->log("SetMimeType('$mimeType')"); $sql="UPDATE binaries SET mime_type='".addslashes($mimeType)."'"; $this->mBio->mDb->query(&$sql); } function ToFile() { $GLOBALS["gAppLog"]->log("ToFile()"); if($this->IsFile()) return; $data=&$this->GetData(); $h=fopen($this->GetPath(), "w"); fwrite($h,&$data,strlen(&$data)); fclose($h); $sql="UPDATE binaries SET bin_data=NULL WHERE id='".$this->mId."'"; $this->mBio->mDb->query(&$sql); } function ToDb() { $GLOBALS["gAppLog"]->log("ToDB()"); if(!$this->IsFile()) return; $data=&$this->GetData(); $sql="UPDATE binaries SET bin_data='".addslashes($data)."' WHERE id='".$this->mId."'"; $this->mBio->mDb->query(&$sql); $path=$this->GetPath(); if($path!=null) if(file_exists($path)) unlink($path); } function IsFile() { $GLOBALS["gAppLog"]->log("IsFile(".($this->mBio->mConfig["BINARIES_FOLDER"]. "/".$this->mId.".bin").")=".file_exists($this->mBio->mConfig["BINARIES_FOLDE R"]."/".$this->mId.".bin")); return file_exists($this->mBio->mConfig["BINARIES_FOLDER"]."/".$this->mId.".bin"); } function IsDataPresent() { $GLOBALS["gAppLog"]->log("IsDataPresent()"); if($this->IsFile()) { return filesize($this->mBio->mConfig["BINARIES_FOLDER"]."/".$this->mId.".bin")!=0; } else { $sql="SELECT id FROM binaries WHERE bin_data IS NOT NULL AND id='".$this->mId."'"; $this->mBio->mDb->query($sql); return $this->mBio->mDb->next_record(); } } function GetSize() { $GLOBALS["gAppLog"]->log("GetSize()"); if($this->IsDataPresent()) { if($this->IsFile()) { return filesize($this->mBio->mConfig["BINARIES_FOLDER"]."/".$this->mId.".bin"); } else { $sql="SELECT LENGTH(bin_data) FROM binaries WHERE id='".$this->mId."'"; $this->mBio->mDb->query($sql); $this->mBio->mDb->next_record(); return $this->mBio->mDb->f(0); } } return 0; } function ToString() { return "[BinaryObject: mId='$this->mId', mMimeType='$this->mMimeType']"; } } ?> ______________________________ lib/binlib/bin.php - выводит бинарный объект в стандартный вывод ______________________________ <?php require_once "../../init_pear.php"; require_once "binlib/BinariesIO.php"; include("phplib/prepend.php3"); $bio_db=&new DB_Example; $bio=&new BinariesIO($BinariesIOConfig, $bio_db); $bo=$bio->GetBinaryObject($id); if($bo==null) { echo "no data present"; exit; } if($bo->GetMimeType()!="") Header("Content-type: ".$bo->GetMimeType()); echo ($bo->GetData()); ?> ______________________________ lib/binlib/testing/up_action.php - загрузка файла в систему ______________________________ <?php require_once "../../../init_pear.php"; require_once "binlib/BinariesIO.php"; include("phplib/prepend.php3"); if($myfile!="") { $GLOBALS["gAppLog"]->log("file: '$myfile'"); $bio_db=&new DB_Example; $bio=&new BinariesIO($BinariesIOConfig, $bio_db); $bo=$bio->GetBinaryObject($id); if($bo==null) { $bo=$bio->CreateBinaryObject(); } $bo->SetDataFromMultipartRequest($myfile); $bo->SetMimeType($mime); } $d="Location: up_view.php?id=".$bo->mId; header($d); exit; ?> ______________________________ lib/binlib/testing/up_convert.php - смена типа хранилища БД-файл/файл-БД ______________________________ <? require_once "../../../init_pear.php"; require_once "binlib/BinariesIO.php"; include("phplib/prepend.php3"); $GLOBALS["gAppLog"]->log("*** SCRIPT START ***"); $bio_db=&new DB_Example; $bio=&new BinariesIO($BinariesIOConfig, $bio_db); $bo=$bio->GetBinaryObject($id); if($bo->IsFile()) $bo->ToDb(); else $bo->ToFile(); $GLOBALS["gAppLog"]->log($bo->ToString()); $GLOBALS["gAppLog"]->log("*** SCRIPT END ***"); header("Location: up_view.php?id=$id"); exit; ?> ______________________________ lib/binlib/testing/up_delete.php - удаление бинарного объекта ______________________________ <? require_once "../../../init_pear.php"; require_once "binlib/BinariesIO.php"; include("phplib/prepend.php3"); $GLOBALS["gAppLog"]->log("*** SCRIPT START ***"); $bio_db=&new DB_Example; $bio=&new BinariesIO($BinariesIOConfig, $bio_db); $bo=$bio->RemoveBinaryObject($id); $GLOBALS["gAppLog"]->log("*** SCRIPT END ***"); header("Location: up_view.php"); exit; ?> ______________________________ lib/binlib/testing/up_view.php - управление списком бинарных объектов ______________________________ <?php require_once "../../../init_pear.php"; require_once "binlib/BinariesIO.php"; include("phplib/prepend.php3"); $bio_db=&new DB_Example; $bio=&new BinariesIO($BinariesIOConfig, $bio_db); $bo=$bio->GetBinaryObject($id); if($bo==null) { $data="no data present"; } else { $mime=$bo->GetMimeType(); if($bo->IsDataPresent()) { $data=&$bo->GetData(); } else { $data="no data present"; } } ?> <?if($data!="no data present"){?><img src="<?=$BinariesIOConfig["BINSCRIPT_URI"]?>?id=<?=$id?>"><?}?> <form method="POST" action="up_action.php" enctype="multipart/form-data"> <input type="hidden" name="id" value="<?=$id?>"> <input type="file" name="myfile"><br> MIME Type: <input type="text" name="mime" value="<?=$mime?>"><br> <input type="submit" value="Upload"> </form> <table border="1"> <tr> <td>ID</td> <td>Type</td> <td>Size</td> <td>Store</td> <td>Convert</td> <td>Delete</td> </tr> <?php $boList=$bio->GetBinaryObjectList(); for($i=0,$s=sizeof($boList);$i<$s;$i++) { ?> <tr> <td><a href="up_view.php?id=<?=$boList[$i]->mId?>"><?=$boList[$i]->mId?></a></td> <td><?=$boList[$i]->mMimeType==""?"UNKNOWN":$boList[$i]->mMimeType?></td> <td><?=$boList[$i]->GetSize()?></td> <td><?=$boList[$i]->IsFile()?"FILE":"DB"?></td> <td><a href="up_convert.php?id=<?=$boList[$i]->mId?>"><?=$boList[$i]->IsFile()?"TO DB":"TO FILE"?></a></td> <td><a href="up_delete.php?id=<?=$boList[$i]->mId?>">delete</a></td> </tr> <? } ?> </table> <a href="up_view.php">add new</a> ______________________________ init_pear.php ______________________________ <? $DOCUMENT_ROOT=eregi_replace("(.*)/$","\\1",$DOCUMENT_ROOT); $include_path_old=@ini_get("include_path"); if($DOCUMENT_ROOT[0]=='/') @ini_set("include_path",$include_path_old.":".$DOCUMENT_ROOT."/pear".":".$DO CUMENT_ROOT.":".$DOCUMENT_ROOT."/lib"); else @ini_set("include_path",$include_path_old.";".$DOCUMENT_ROOT."/pear".":".$DO CUMENT_ROOT.":".$DOCUMENT_ROOT."/lib"); require_once "log/MyLog.php"; // **GLOBAL*CONFIGURATION**************************************************** // $gAppLog=&new MyLog(); $gAppLog->setLogging(true); $gAppLog->setEcho(false); $BinariesIOConfig["BINARIES_FOLDER"]=$GLOBALS["DOCUMENT_ROOT"]."/binaries"; $BinariesIOConfig["BINSCRIPT_URI"]="/lib/binlib/bin.php"; ?> ______________________________ log/MyLog.php - класс протокола ______________________________ <? require_once "Log.php"; require_once "Log/file.php"; class MyLog { var $mLog; var $mLogging; var $mEcho; function MyLog() { $this->mLog=new Log_file($GLOBALS["DOCUMENT_ROOT"]."/app.log"); $this->mLogging=true; $this->mEcho=false; } function setEcho($onTrueOffFalse) { $this->mEcho=$onTrueOffFalse; } function setLogging($onTrueOffFalse) { $this->mLogging=$onTrueOffFalse; } function log($message) { $this->debug($message); } function debug($message) { if($this->mLogging) $this->internalLog($message,"debug"); } function error($message) { if($this->mLogging) $this->internalLog($message,LOG_ERR); } function info($message) { if($this->mLogging) $this->internalLog($message,"info"); } function warning($message) { if($this->mLogging) $this->internalLog($message,LOG_INFO); } function fatal($message) { if($this->mLogging) $this->internalLog($message,LOG_CRIT); } function internalLog(&$message, $priority) { if($this->mEcho) echo "<b>[$message]</b><br>\n"; $this->mLog->log("[".$GLOBALS["PHP_SELF"]."] ".$message); } } ?>

<< Предыдущая ИНДЕКС Поиск в статьях src Установить закладку Перейти на закладку Следующая >>

Обсуждение [ Линейный режим | Показать все | RSS ]
  • 1.1, nexel (?), 11:15, 12/07/2007 [ответить] [﹢﹢﹢] [ · · · ]  
  • +/
    в многоюзерском режиме может вернуть лажу:
    $sql="SELECT MAX(id) from binaries";
    лучше так
    $sql="SELECT LAST_INSERT_ID()"
     
  • 1.2, Papa (?), 10:55, 24/01/2008 [ответить] [﹢﹢﹢] [ · · · ]  
  • +/
    Около пяти лет профессионально занимаюсь созданием подобных вещей. Имхо, автор абсолютно не интересовался данным вопросом, хотя бы так как это реализовано в больших коммерческих проектах.
     
     
  • 2.4, alexzh (??), 16:09, 02/02/2008 [^] [^^] [^^^] [ответить]  
  • +/
    Подскажи как реализовано в больших комерческих проектах. Очень интересная тема и будет полезна многим. Очень хочется увидеть как делают професионалы, дабы было с чем сравнивать.
     

  • 1.3, latteo.org.ua (?), 00:12, 30/01/2008 [ответить] [﹢﹢﹢] [ · · · ]  
  • +1 +/
    Может кому не жалко для новичка, самый элиментарный пхп скрипт который "засунет" картинку в MySQL
     
  • 1.5, Guest (??), 18:03, 16/04/2008 [ответить] [﹢﹢﹢] [ · · · ]  
  • +/
    Imxo метод 1 в крупных проекта будет нагружать БД. Лучше 2-ой метод. Картинки - не настолько важная информация, чтобы контролировать жестко доступ. Думаю, в полне можно обойтись одной папкой с общим доступом на чтение.
     
  • 1.6, Сергей (??), 18:50, 23/12/2008 [ответить] [﹢﹢﹢] [ · · · ]  
  • +/
    столкнулся с проблемой, в таблице 50000 картинок общим объемом 300MB, select count(*) from image; выполняется 30 сек, это нормально или у меня что-то не так с MySQL?
     
     
  • 2.7, error500 (??), 18:53, 07/04/2009 [^] [^^] [^^^] [ответить]  
  • +/
    у тебя что то не так с головой
    И вообще хранение бинарников в базе (таких как картинки) для веб проектов может придумать только человек срочно нуждающийся в медицинской помощи.
     

  • 1.8, Веб (?), 01:13, 24/03/2010 [ответить] [﹢﹢﹢] [ · · · ]  
  • +/
    Сам ты больной на голову что схочу то и напишу.
     
     
  • 2.11, Аркадий (??), 11:32, 13/08/2011 [^] [^^] [^^^] [ответить]  
  • +/
    А Вы, случайно, не в мелокомягких работаете? А то что-то мне подсказывает, что они руководствуются тем же принципом.
     

  • 1.9, leon (??), 17:54, 21/11/2010 [ответить] [﹢﹢﹢] [ · · · ]  
  • +/
    // select count(*) from image
      
      так  делай count по  индексному  полю  
      иначе  ,  естетстенно  будет  строки пересчитывать
      
     
  • 1.10, АзатотазА (?), 20:44, 04/02/2011 [ответить] [﹢﹢﹢] [ · · · ]  
  • +/
    В up_view.php две части верно? или вторая часть это отдельный файл?
     

     Добавить комментарий
    Имя:
    E-Mail:
    Заголовок:
    Текст:




    Партнёры:
    PostgresPro
    Inferno Solutions
    Hosting by Hoster.ru
    Хостинг:

    Закладки на сайте
    Проследить за страницей
    Created 1996-2024 by Maxim Chirkov
    Добавить, Поддержать, Вебмастеру