Sqlserver
 sql >> Baza danych >  >> RDS >> Sqlserver

Jak ustawić wyrażenie we właściwości FileSpec w module wyliczającym plików Foreach?

Od zbadania, jak działa pętla ForEach w SSIS (z myślą o stworzeniu własnej w celu rozwiązania problemu) wydaje się, że sposób działania (o ile mogłem to zobaczyć) polega na wyliczeniu kolekcji plików, zanim jakakolwiek maska ​​zostanie określony. Trudno powiedzieć dokładnie, co się dzieje, nie widząc kodu dla pętli ForEach, ale wydaje się, że robi to w ten sposób, co skutkuje niską wydajnością podczas obsługi ponad 100k plików.

Chociaż rozwiązanie @Siva jest fantastycznie szczegółowe i zdecydowanie stanowi poprawę w stosunku do mojego początkowego podejścia, jest to zasadniczo ten sam proces, z wyjątkiem użycia zadania wyrażenia do testowania nazwy pliku, a nie zadania skryptu (wydaje się to oferować pewną poprawę).

Postanowiłem więc przyjąć zupełnie inne podejście i zamiast używać pętli ForEach opartej na plikach, samodzielnie wyliczyć kolekcję w zadaniu skryptu, zastosować moją logikę filtrowania, a następnie wykonać iterację pozostałych wyników. Oto co zrobiłem:

W moim zadaniu skryptu używam asynchronicznego DirectoryInfo.EnumerateFiles Metoda, która jest zalecanym podejściem w przypadku dużych kolekcji plików, ponieważ umożliwia przesyłanie strumieniowe, zamiast czekać na utworzenie całej kolekcji przed zastosowaniem jakiejkolwiek logiki.

Oto kod:

public void Main()
{
    string sourceDir = Dts.Variables["SourceDirectory"].Value.ToString();
    int minJobId = (int)Dts.Variables["MinIndexId"].Value;

    //Enumerate file collection (using Enumerate Files to allow us to start processing immediately
    List<string> activeFiles = new List<string>();

    System.Threading.Tasks.Task listTask = System.Threading.Tasks.Task.Factory.StartNew(() =>
    {
         DirectoryInfo dir = new DirectoryInfo(sourceDir);
         foreach (FileInfo f in dir.EnumerateFiles("*.txt"))
         {
              FileInfo file = f;
              string filePath = file.FullName;
              string fileName = filePath.Substring(filePath.LastIndexOf("\\") + 1);
              int jobId = Convert.ToInt32(fileName.Substring(0, fileName.IndexOf(".txt")));

              if (jobId > minJobId)
                   activeFiles.Add(filePath);
         }
    });

    //Wait here for completion
    System.Threading.Tasks.Task.WaitAll(new System.Threading.Tasks.Task[] { listTask });
    Dts.Variables["ActiveFilenames"].Value = activeFiles;
    Dts.TaskResult = (int)ScriptResults.Success;
}

Tak więc wyliczam kolekcję, stosując moją logikę, gdy pliki są wykrywane i natychmiast dodając ścieżkę pliku do mojej listy w celu uzyskania danych wyjściowych. Po zakończeniu przypisuję to do zmiennej obiektu SSIS o nazwie ActiveFilenames którego użyję jako kolekcji dla mojej pętli ForEach.

Skonfigurowałem pętlę ForEach jako ForEach From Variable Enumerator , który teraz iteruje po znacznie mniejszej kolekcji (po filtrowaniu List<string> w porównaniu do tego, co mogę tylko założyć, było niefiltrowanym List<FileInfo> lub coś podobnego we wbudowanym Enumeratorze plików ForEach .

Tak więc zadania w mojej pętli mogą być przeznaczone tylko do przetwarzania danych, ponieważ zostały one już przefiltrowane przed trafieniem w pętlę. Chociaż wydaje się, że nie różni się to zbytnio od mojego początkowego pakietu lub przykładu Siva, w produkcji (w każdym razie w tym konkretnym przypadku) wydaje się, że filtrowanie kolekcji i asynchroniczne wyliczanie zapewnia ogromny wzrost w zakresie korzystania z wbudowanego pliku ForEach Numerator.

Zamierzam kontynuować badanie kontenera pętli ForEach i sprawdzić, czy mogę replikować tę logikę w komponencie niestandardowym. Jeśli to działa, opublikuję link w komentarzach.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. procedury składowane z sqlAlchemy

  2. Jak przekonwertować String na Hex i odwrotnie?

  3. Wyszukaj i zamień całą wartość kolumny SQL Server

  4. jak pobrać dane z bieżącego tygodnia tylko na serwerze SQL?

  5. Suma podzapytań w SQL Server