Problem z generowaniem listy plików do bazy danych

0

Witam

Napisałem program w C# i .NET do wrzucania listy plików do bazy danych na serwerze. Mam tylko jeden problem. Gdy plików jest więcej niż 100 program robi to bardzo powoli. Jak wrzucić listę takich nazw do tabeli, ale bardzo szybko? Plików jest około 400 tys.

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using MySql.Data.MySqlClient;
using System.IO;

namespace SynchronizujPliki
{
    public partial class Form1 : Form
    {
        private MySqlConnection polaczenieServer;
        private MySqlCommand ZapytajSerwer;  
        private string polaczenieDane;
        private string Serwer;
        private string BazaDanych;
        private string Login;
        private string Haslo;

        private string PlikiWKatalogu;
        private int IloscPlikow;
        private string DodajPlik;
        private string PlikiGotowe;

        public Form1()
        {
            InitializeComponent();
        }

        List<string> ListaPlikow = new List<string>();

        private void SynchronizujPliki_Click(object sender, EventArgs e)
        {
            SynchronizujPliki.Enabled = false;
            SynchronizujPliki.Text = "Czekaj...";

            // Połączenie z bazą danych

                Serwer = "localhost";
                BazaDanych = "pliki";
                Login = "root";
                Haslo = "";

                polaczenieDane = "SERVER=" + Serwer + ";" + "DATABASE=" +
                BazaDanych + ";" + "UID=" + Login + ";" + "PASSWORD=" + Haslo + ";";

                polaczenieServer = new MySqlConnection(polaczenieDane);

                try
                {
                    polaczenieServer.Open();
                }
                catch (MySqlException ex)
                {
                    switch (ex.Number)
                    {
                        case 0:
                            MessageBox.Show("Błąd połączenia z serwerem");
                            break;

                        case 1045:
                            MessageBox.Show("Zły login lub hasło do bazy danych");
                            break;
                        default:
                            MessageBox.Show("Błąd: " + ex.Message);
                            break;
                    }
                }

            // Pobieranie listy plików
                string[] PlikiWKatalogu;

                try
                {
                    var PlikiWKatalogu2 = Directory.EnumerateFiles("C:/KatalogPliki", "*", SearchOption.TopDirectoryOnly).Select(Path.GetFileName); 

                    foreach (string PlikWKatalogu in PlikiWKatalogu2)
                    {
                        ListaPlikow.Add(PlikWKatalogu);
                    }
                    
                }
                catch (IOException exp)
                {
                    MessageBox.Show("Błąd: " + exp.GetType().Name);
                }

            // Liczenie ilości plików

                IloscPlikow = ListaPlikow.Count();

                PoleWynikow.Text = "Ilość plików: " + IloscPlikow;

            // Umieszczanie listy plików

                string ZapytanieSQLDoBazy;

                ZapytanieSQLDoBazy = "TRUNCATE TABLE pliki;";

                ZapytajSerwer = polaczenieServer.CreateCommand();
                ZapytajSerwer.CommandText = ZapytanieSQLDoBazy;
                ZapytajSerwer.ExecuteNonQuery();  

                for(int i = 0; i < ListaPlikow.Count(); i++)
                {
                    //PlikiGotowe;

                    PoleWynikow.Text += ListaPlikow[i];

                    ZapytanieSQLDoBazy = "INSERT INTO pliki (id,plik)  VALUES  (NULL,@plik_nazwa);";

                    ZapytajSerwer = polaczenieServer.CreateCommand();
                    ZapytajSerwer.CommandText = ZapytanieSQLDoBazy;
                    ZapytajSerwer.Parameters.AddWithValue("@plik_nazwa", ListaPlikow[i]);
                    ZapytajSerwer.ExecuteNonQuery();  
                }

            // Rozłączenie z bazą danych

                try
                {
                    polaczenieServer.Close();
                }
                catch (MySqlException ex)
                {
                    MessageBox.Show("Błąd: " + ex.Message);
                }

            // Komunikat i zakończenie
                SynchronizujPliki.Enabled = true;
                SynchronizujPliki.Text = "Synchronizuj";
        }
    }
}

0

Po co tak:

                    foreach (string PlikWKatalogu in PlikiWKatalogu2)
                    {
                        ListaPlikow.Add(PlikWKatalogu);
                    }                    

Skoro można tak:

listaPlikow.AddRange(plikiWKatalogu2);

Nie rozumiem też, po co wielokrotnie wywołujesz na List<T> metodę Count(), skoro jest już właściwość Count, która nie wymaga każdorazowego przechodzenia po kolekcji, więc jest szybsza.

A powolne działanie może wynikać z tego, że każdy INSERT robisz w niejawnej transakcji zamiast wykonać wszystkie w jednej. (Strzelam, bo nie wiem, czy MySQL w ogóle obsługuje transakcje.)

Najlepiej użyj klasy Stopwatch do zmierzenia czasu poszczególnych operacji (listowania plików, wstawiania do bazy), to będziesz wiedział, co trwa najdłużej, więc będzie można myśleć, co dalej z tym zrobić.

0

Powinieneś wyłączyć autocommit i ręcznie robić commit co jakieś 1000 rekordów, to znacznie przyśpieszy proces. Kolejna sprawa, że operowanie na katalogu, który ma 400k plików, może być masakrycznie wolne. Generalnie - jak wyżej - ustal najpierw wąskie gardło.

1 użytkowników online, w tym zalogowanych: 0, gości: 1