Tagi na forum.

C# 1456 XML 282
SQL 1192 sieci 268
ASP.NET 785 IIS 262
Windows 726 C++ 255
web 608 Html 218
Visual Studio 515 Information Technology 193
SQL Server 425 MSDN 167

pokaż wszystkie tagi na forum

tranzakcje

kobr 2011-04-17 14:39:03
0
avatar
 
 
Witam, moim zadaniem jest wybranie z plików xml 10 milionów rekordów i wrzucenie ich do bazy mysql. W tym celu napisałem aplikację desktopową i wszystko ładnie śmiga. Problemem jest jedynie czas. Przy obecnym programie te 10 milionów do bazy będę dodawał kilka tygodni. Wąskim gardłem jest to iż oprogramowanie z plikami xml uruchomione jest na moim dysku a baza mysql na serwerze zewnętrznym. Rekordy dodawane są w w transakcji. Teraz aby to przyspieszyć postanowiłem uruchomić program na kilku komputerach i przerobić aplikację na wielowątkową. Tak aby równocześnie dodawało kilka rekordów (jako, że większość czasu tracę na przesyłanie danych między serwerem a moim komputerem). Zastanawia mnie, czy jeśli jednocześnie będę dodawał rekordy z kilku wątków i komputerów to czy wszystko nie popsuje się. Chodzi mi głównie o fakt iż po dodaniu rekordu, pobieram jego id i wpisuje je do relacyjnej tabeli.
Będę wdzięczny za każdą propozycję przyspieszającą wszystkie operacje. Jako że baza jest mocno indeksowana to zastanawiam się jeszcze nad tym ile czasu będzie trwało dodawanie rekordów gdy w bazie będzie już ich kilka milionów.
 
Zamieszczam skrócony kod wszystkich operacji:
 
 



[Kod]
SqlObiekt = new MySqlCommand();
SqlObiekt.Connection = conn;
SqlObiekt.CommandType = CommandType.Text;


#region//sprawdzenie czy taki rekord istnieje
SqlObiekt.CommandText = "SELECT `id` FROM `book` WHERE `code`=@code";
SqlObiekt.Parameters.AddWithValue
conn.Open();

MySqlDataReader reader;
reader = SqlObiekt.ExecuteReader();

myBook.BookSQLID=-1;
if (reader.HasRows)
{
while (reader.Read())
{
myBook.BookSQLID = (int)reader["id"];
}
}
reader.Close();
#endregion
#region//sprawdzenie czy istnieje publisher
SqlObiekt.CommandText = "SELECT `id` FROM `publisher` WHERE `name`=@name";
SqlObiekt.Parameters.AddWithValue("name", myPublisher.PublisherName);

reader = SqlObiekt.ExecuteReader();

myPublisher.PublisherID = -1;
if (reader.HasRows)
{
while (reader.Read())
{
myPublisher.PublisherID = (int)reader["id"];
}
}
reader.Close();
#endregion
#region//sprawdzenie czy istnieje autor
foreach (Author aut in myAuthorList)
{
SqlObiekt.Parameters.Clear();
SqlObiekt.CommandText = "SELECT `id` FROM `author` WHERE `name`=@authorName AND `surname`=@authorSurname";
SqlObiekt.Parameters.AddWithValue("authorName", aut.NamesBeforeKey);
SqlObiekt.Parameters.AddWithValue("authorSurname", aut.KeyNames);

reader = SqlObiekt.ExecuteReader();

aut.AuthorID=-1;
if (reader.HasRows)
{

Edytowano 3 razy. Ostatnio 2011-04-17 14:42:21 przez kobr.
tagi: mysql   XML


szogun.krepa  2011-04-18 01:44:14 #1
0
avatar
 
 
Mysle ze wysylanie danych z wielu komputerow moze okazac sie nawet wolniejsze niz z jednego(serwer bedzie musial wykonac wiecej pracy w celu rozwiazania problemow wspolbierznosci. Proponuje ci podzielenie kazdego pliku na spojne kawalki i import tylko kawalkow. Przy jakims (pewnie nie malym) wysilku jestes w stanie napisac program ktory bedzie partycjonowal dla ciebie pliki.--if (PomoglCi)
{
Click("Pomógł mi");
}
Strona szoguna

if (PomoglCi)

{

Click("Pomógł mi");

}

Strona szoguna

kobr  2011-04-18 08:25:35 #1.1
0
avatar
 
 
W jaki sposób partycjonował? Pliki xml są po 5000 rekordów więc nie ma chyba sensu ich dzielić jeszcze bardziej jeśli to miałeś na myśli. Teraz serwer praktycznie nic nie robi poza obsługą moich zapytań. Myślałem o rozbiciu tego powiedzmy na 3 wątki i uruchomienie programu na 2 komputerach więc to chyba nie jest duże obciążenie serwera. Interesuje mnie tylko jak serwer sobie z tym poradzi, czy nie będzie zakłamań typu w jednej transakcji dodałem nowego autora, w drugiej sprawdziłem czy taki istnieje, okazało sie że nie istnieje bo transakcja jeszcze nie była zatwierdzona i raptem po zatwierdzeniu transakcji dostaje 2 takich samych autorów.

Edytowano 1 raz. Ostatnio 2011-04-18 08:28:20 przez kobr.
szogun.krepa  2011-04-18 19:16:05 #1.1.1
0
avatar
 
 
Tranzakcje są izolowane i jeżeli występuje między nimi konflikt (np. Obie chcą używać tabeli z Autorem  przy czym przynajmniej jedna do zapisu), to jedna tranzakcja będzie czekała aż druga się zakończy.
Skoro pliki masz podzielone to najlepiej zrobisz jak zastosujesz zasadę 1 tranzakcja 1 plik i dodatkowo wprowadzisz jakiś mechanizm oznaczający pliki jako zaimportowane (np. przeniesienie do innego folderu. Jeżeli tranzakcja z jakiegoś powodu się nie zakończy to wycofana zostanie mała ilość danych, a sam import będziesz mógł rozpocząć od punktu w którym go przerwałeś. Jedyną wadą tego rozwiązania (jakie widzę) jest fakt że jeżeli na bazie pracuje inny program to przez jakiś czas będzie dysponował niekompletnymi danymi.--if (PomoglCi)
{
Click("Pomógł mi");
}
Strona szoguna

if (PomoglCi)

{

Click("Pomógł mi");

}

Strona szoguna

kobr  2011-04-18 22:49:12 #1.1.1.1
0
avatar
 
 
Właśnie tak zrobiłem, na bazie będą działały tylko moje programy wrzucające dane więc raczej nie powinno być z tym problemu i prawdopodobieństwo jakiejś kolizji jest bardzo małe.

Udziel odpowiedzi

avatar
Treść wpisu:

Zaloguj się lub Zarejestruj się aby wykonać tę czynność.

Idź na górę strony