Я работаю над проектом, который предполагает сохранение большого количества изображений в базу данных. Однако я допустил ошибку. Я включил фактическое изображение в таблицу image , которая является той же таблицей, которая содержит метаданные. Это требует, чтобы я всегда загружал изображение, даже когда мне нужны только метаданные, что происходит довольно часто.
Я не буду go вдаваться в подробности метаданных, поскольку они не имеют отношения к этому вопросу. Но в основном это временная метка, varchar (255) и два логических значения (так что ничего страшного).
Чтобы исправить свою ошибку, я создал новую таблицу с именем ImageBlob , которая содержит только изображение и идентификатор, на который ссылаются сущности в таблице Image .
Затем я написал фрагмент кода (используя EF Core 3.0.0) для перемещения данных из * 1013. * Image таблица к таблице ImageBlob . Этот код, однако, невероятно медленный. (Он работал около 12 часов, и это только на 40%.)
Я пытаюсь переместить 120.000 изображений. Всего 200 000 записей, из которых 80 000 не содержат изображения. Вся база данных составляет около 150 ГБ.
Мой вопрос: я что-то упускаю или есть более эффективный способ сделать это?
Код для перемещения изображений:
using (var context = new MakeModelContext())
{
List<int> imageIds = context.Images
.Where(x => x.IsAcquired)
.Select(x => x.Id)
.ToList();
foreach (int imageId in imageIds)
{
Image image = context.Images.Where(x => x.Id == imageId).Single();
if (image.Picture != null)
{
image.ImageBlob = new ImageBlob(image.Picture);
image.Picture = null;
context.SaveChanges();
}
}
}
Image.cs:
public class Image
{
[Required]
public int Id { get; set; }
public byte[] Picture { get; set; }
public ImageBlob ImageBlob { get; set; }
// Metadata redacted
}
ImageBlob.cs:
public class ImageBlob
{
[Required]
public int Id { get; set; }
public byte[] Blob { get; set; }
public ImageBlob(byte[] blob)
{
this.Blob = blob;
}
}
РЕДАКТИРОВАТЬ: Решение, предложенное sdi
Спасибо за ваш ответ. Я изменил код для обработки изображений партиями по 100. Несмотря на то, что я ожидал некоторых дополнительных затрат от отдельных запросов, я не ожидал, что это окажет такое большое влияние на производительность!
Я рассматривал SaveChangesASyn c () но я думаю, что это может вызвать конфликты, так как программа может извлечь изображения, которые уже перемещены, но для которых изменения еще не были полностью сохранены.
Это, как говорится. Производительность все еще не велика, но определенно достаточна для одноразовой работы. В настоящее время я управляю около 6 МБ / с.
Модифицированный код:
using (var context = new MakeModelContext())
{
bool done = false;
while (!done)
{
List<Image> image_batch = context.Images
.Where(x => x.IsAcquired && x.Picture != null)
.Take(100)
.ToList();
if (image_batch.Count < 100)
{
done = true;
}
foreach (Image image in image_batch)
{
image.ImageBlob = new ImageBlob(image.Picture);
image.Picture = null;
}
context.SaveChanges();
}
}