Inhalte aufrufen

Profilbild

Überflüssige Daten aus MediaStorage löschen

sql media bilder delete löschen

  • Bitte melden Sie sich an, um eine Antwort zu verfassen.
6 Antworten zu diesem Thema

#1 RIM

RIM

    Newbie

  • Members
  • 8 Beiträge

Geschrieben: 04 March 2020 - 15:47

Hallo zusammen, 

 

ich finde ja grundsätzlich das Soft-Delete Konzept von Smartstore wirklich sinnig: Inhalte werden nicht gelöscht, sondern auf Deleted gestellt. 

Jetzt hat sich aber durch dieses Verfahren in unserer MediaStorage Tabelle ein Datenbestand von einigen GB ergeben, die ich gerne mal bereinigen würde. 

 

Hat jemand ein SQL Statement für mich, dass keine vorhandenen Produkte, Logos, Waregnruppen usw. entfernt und die wirklich überflüssigen Binärdaten aus der MediaStorage Tabelle löscht?

 

 

Danke schon mal

Lars



#2 Marcus Gesing

Marcus Gesing

    SmartStore AG

  • Administrators
  • 3502 Beiträge

Geschrieben: 05 March 2020 - 12:07

Ein SQL-Skript habe ich leider nicht dafür, und ich würde es vermutlich auch nicht per SQL machen, sondern einen Bereinigungstask schreiben.
MediaStorage ist mit Picture, Download und QueuedEmailAttachment verknüpft, d.h. alle Datensätze die nicht über MediaStorageId mit diesen drei Tabellen verknüpft sind, können gelöscht werden.

Schöne Grüße aus Düsseldorf,
Marcus Gesing


#3 RIM

RIM

    Newbie

  • Members
  • 8 Beiträge

Geschrieben: 05 March 2020 - 14:09

Hi Marcus

 

besten Dank für die Antwort.
1. Wie schreibt man einen Bereinigungstask?
2. Ich habe jetzt mal nur ein Join auf die picture-Tabelle gelegt und komme auf über 200.000 Daten. Ich vermute, dass das etwas mit den mehrfachen Importen zu tun hat, die wir automatisiert durchgeführt hatten. Danach haben wir zwar ein Script, um die Datensätze aus der product-Tabelle zu löschen, aber die picture-Tabelle hatten wir nicht angefasst. Ich bin aber gerade überfragt, wie ich da die überflüssigen löschen könnte. 

 

Lars



#4 Marcus Gesing

Marcus Gesing

    SmartStore AG

  • Administrators
  • 3502 Beiträge

Geschrieben: 05 March 2020 - 14:51

1. Eine neue Klasse erstellen, die ITask oder IAsyncTask implementiert. Einfaches Beispiel hierfür ist TempFileCleanupTask.
Dann muss nur noch ein Datensatz in ScheduleTask (mit Enabled = False) für diesen Task hinzugefügt werden (entweder per Migration oder manuell), damit er auch in der Task-Liste im Backend erscheint und manuell gestartet werden kann.
 
2. Im Prinzip genauso. PictureId aus den Tabellen Category, Manufacturer, Product_Picture_Mapping, ProductVariantAttributeCombination (gibt's noch weitere?) ermitteln. Alle Picture-Datensätze, die nicht über PictureId mit den genannten Tabellen verknüpft sind können gelöscht werden.
 
Wenn es für die MediaStorage-Einträge zugehörige, verknüpfte Picture-Entitäten gibt, dann kann man auch über IPictureService.DeletePicture löschen. Das löscht die MediaStorage-Einträge mit (so als wenn man im Backend manuell ein Produktbild löscht). Das funktioniert aber nur, wenn sich der Speicherort für Medien nicht zwischenzeitlich geändert hat.

Schöne Grüße aus Düsseldorf,
Marcus Gesing


#5 Marcus Gesing

Marcus Gesing

    SmartStore AG

  • Administrators
  • 3502 Beiträge

Geschrieben: 05 March 2020 - 16:43

Hier ist mal etwas ungetesteter Pseudo-Code für einen solchen Task. Datenbank-Backup vor Ausführung nicht vergessen.

public class MyDataCleanupTask : ITask
    {
        private readonly IRepository<ProductPicture> _productPictureRepository;
        private readonly IRepository<Picture> _pictureRepository;
        private readonly ICommonServices _services;
        private readonly Provider<IMediaStorageProvider> _databaseStorageProvider;

        public MyDataCleanupTask(
            IRepository<ProductPicture> productPictureRepository,
            IRepository<Picture> pictureRepository,
            ICommonServices services,
            IProviderManager providerManager)
        {
            _productPictureRepository = productPictureRepository;
            _pictureRepository = pictureRepository;
            _services = services;

            // We want to delete media data from database.
            _databaseStorageProvider = providerManager.GetProvider<IMediaStorageProvider>(DatabaseMediaStorageProvider.SystemName);

            Logger = NullLogger.Instance;
        }

        public ILogger Logger { get; set; }

        public void Execute(TaskExecutionContext ctx)
        {
            try
            {
                using (var scope = new DbContextScope(ctx: _services.DbContext, autoDetectChanges: false, validateOnSave: false, hooksEnabled: false, autoCommit: false))
                {
                    var assignedPictureIds = new HashSet<int>();
                    var pageIndex = 0;
                    IPagedList<Picture> pictures = null;

                    // 1. get all assigned picture ids.
                    assignedPictureIds.AddRange(_productPictureRepository.TableUntracked.Select(x => x.PictureId).ToList());
                    // TODO: same with Category.PictureId, Manufacturer.PictureId, ProductVariantAttributeCombination.AssignedPictureIds...

                    // 2. delete non-referenced pictures.
                    var pictureQuery = _pictureRepository.Table
                        .Where(x => x.MediaStorageId != null)
                        .OrderBy(x => x.Id);

                    do
                    {
                        pictures = new PagedList<Picture>(pictureQuery, pageIndex++, 200);

                        foreach (var picture in pictures)
                        {
                            if (!assignedPictureIds.Contains(picture.Id))
                            {
                                // Similar what PictureService.DeletePicture do.
                                // Delete from storage.
                                _databaseStorageProvider.Value.Remove(picture.ToMedia());

                                // Delete entity.
                                _pictureRepository.Delete(picture);
                            }
                        }

                        // Commit batch.
                        scope.Commit();
                    }
                    while (pictures.HasNextPage);
                }
            }
            catch (Exception ex)
            {
                Logger.Error(ex);
            }
        }
    }

Schöne Grüße aus Düsseldorf,
Marcus Gesing


#6 RIM

RIM

    Newbie

  • Members
  • 8 Beiträge

Geschrieben: 05 March 2020 - 19:19

Hi Marcus,

 

besten Dank für die ausführliche Antwort. Ich sitze gerade am SQL Statement und wollte erst mal rausselektieren, was denn überhaupt gebraucht wird. 
Das sieht dann so aus wie unten. Eventuell ja für jemanden interessant. 

Da kommen bei mir jetzt so ca. 2000 Ergebnisse. Das passt. 

Aber insgesamt sind in der MediaStorage Tabelle über 200.000 Datensätze und ich weiß noch nicht genau, wo die überhaupt herkommen. Das ist ein bisschen viel, um das auf fehlerhafte Importe zurückzuführen.

Bevor ich da was lösche, würde ich gerne nochmal nachfragen: Werden denn z.B. die Bilddaten aus dem Pagebuilder auch in der Mediastorage-Tabelle gespeichert?

 

 

Super wäre, wenn so ein Task irgendwann mal zentral unter dem Wartungs-Bereich im Backend verfügbar wäre:

"remove unused pictures" oder so

 

 

 

*************

select MediaStorage.id, Picture.MediaStorageId, Product_Picture_Mapping.ProductId as product, Category.id as category, Product.MainPictureId as productmainpicture, Manufacturer.PictureId as manufacturer
FROM MediaStorage 
JOIN Picture ON MediaStorage.Id=Picture.MediaStorageId
LEFT JOIN Product_Picture_Mapping ON Picture.Id=Product_Picture_Mapping.PictureId
LEFT JOIN Category ON Picture.id=Category.PictureId
LEFT JOIN Product ON Picture.id=Product.MainPictureId
LEFT JOIN Manufacturer on Picture.id=Manufacturer.PictureId
WHERE
NO Manufacturer.PictureId IS NULL OR NOT Product.MainPictureId IS NULL OR NOT Product_Picture_Mapping.ProductId IS NULL OR NOT Category.Id IS NULL 


#7 Marcus Gesing

Marcus Gesing

    SmartStore AG

  • Administrators
  • 3502 Beiträge

Geschrieben: 05 March 2020 - 21:13

Ja, der PageBuilder nutzt ebenfalls IPictureService, d.h. auch dessen Bilddaten landen in MediaStorage, sofern die Datenbank als Speicherort für Medien festgelegt ist.


Schöne Grüße aus Düsseldorf,
Marcus Gesing



Auch markiert mit einem oder mehrerer dieser Schlüsselwörter: sql, media, bilder, delete, löschen