копирование данных
От: vitalik_4  
Дата: 11.09.07 20:20
Оценка:
Пожалуйста подскажите. Надо прегнать по сетке (128K) часть записей из одной БД MySQL в другую. Пока делаю так:


static int CopyToTMP()
{
uint max_id = uint.Parse(GetXMLData(XMLSECTION.CurrentDataGpsID));
MySqlConnection conn = GetConnection(true);
string comand = "SELECT Mobitel_ID,Message_ID,Latitude,Longitude,Altitude,UnixTime,Speed,Direction,Valid,InMobitelID,Events,Sensor1,Sensor2,Sensor3,Sensor4,Sensor5,Sensor6,Sensor7,Sensor8,LogID,isShow,whatIs,Counter1,Counter2,Counter3,Counter4 FROM datagps WHERE Mobitel_ID IN (SELECT Mobitel_ID FROM mobitels)AND Valid=1 AND Datagps_ID>" +
max_id.ToString()+ " ORDER BY Datagps_ID";
MySqlCommand cmd = new MySqlCommand(comand, conn);
conn.Open();

MySqlConnection rem_conn = GetConnection(false);
MySqlCommand cmd_ = new MySqlCommand("", rem_conn);
rem_conn.Open();

MySqlDataReader reader = cmd.ExecuteReader();
Console.WriteLine();
int count = 0;
while (reader.Read())
{
cmd_.CommandText = "INSERT INTO datagps(Mobitel_ID,Message_ID,Latitude,Longitude,Altitude,UnixTime,Speed,Direction,Valid,InMobitelID,Events,Sensor1,Sensor2,Sensor3,Sensor4,Sensor5,Sensor6,Sensor7,Sensor8,LogID,isShow,whatIs,Counter1,Counter2,Counter3,Counter4) VALUES(" +
reader[0] + "," + reader[1] + "," + reader[2] + "," + reader[3] +
"," + reader[4] + "," + reader[5] + "," + reader[6] + "," + reader[7] +
"," + reader[8] + "," + reader[9] + "," + reader[10] + "," + reader[11] +
"," + reader[12] + "," + reader[13] + "," + reader[14] + "," + reader[15] +
"," + reader[16] + "," + reader[17] + "," + reader[18] + "," + reader[19] +
"," + reader[20] + "," + reader[21] + "," + reader[22] + "," + reader[23] +
"," + reader[24] + "," + reader[25] + ")";

Console.Clear();
Console.WriteLine("{0}", count);
count += cmd_.ExecuteNonQuery();
}
reader.Close();
rem_conn.Close();
conn.Close();
return count;
}

По 100Мбитной локалке 1млн. записей перегоняется за 18мин, сколько это будет на 128К даже считать не хочу .
Понимаю, код кривой, и никуда не годится... подскажите как его сделать не таким кривым. Интересует повышение
скорости и надежности работы. Использовать транзакции ? А как ? Для каждого INSERTa свою транзакцию ? Или одну для
всех INSERTов ? Если можно киньте примеры кода, или хоть подскажите в каком направлении копать. Заранее спасибо.
Re: копирование данных
От: IqwertyI  
Дата: 12.09.07 03:27
Оценка:
Здравствуйте, vitalik_4, Вы писали:

_>По 100Мбитной локалке 1млн. записей перегоняется за 18мин, сколько это будет на 128К даже считать не хочу .

_>Понимаю, код кривой, и никуда не годится... подскажите как его сделать не таким кривым. Интересует повышение
_>скорости и надежности работы. Использовать транзакции ? А как ? Для каждого INSERTa свою транзакцию ? Или одну для
_>всех INSERTов ? Если можно киньте примеры кода, или хоть подскажите в каком направлении копать. Заранее спасибо.
Мне кажется проблема в выполнении 1млн Insert-ов, надо от этого уходить использованием xml или еще каких нибудь структур данных, хотя я не знаком с возможностями MySql. И конечно надо использовать транзакции:

MySqlConnection rem_conn = GetConnection(false);
rem_conn.Open();
MySqlTransaction tr = rem_conn.BeginTransaction();
MySqlCommand cmd_ = new MySqlCommand("", rem_conn);
...
tr.Commit();
Re: копирование данных
От: Sinclair Россия https://github.com/evilguest/
Дата: 12.09.07 03:55
Оценка: 1 (1) +2 :)))
Здравствуйте, vitalik_4, Вы писали:

Во-первых, возьми карандащ, бумагу, и четыре миллиона раз напиши "я никогда не буду передавать параметры в SQL стейтмент при помощи конкатенации". Изучи, как правильно передавать параметры.
Во-вторых, срочно изучи как пользоваться using.
В третьих, в цикле нужно делать как можно меньше работы. В частности, вывод на консоль отжирает и без того ценное время. Хочется следить за прогрессом — выводи count раз в секунду.
В четвертых, почитай документацию по своему провайдеру, и выясни, можно ли использовать batch — т.е. несколько SQL команд в одном запросе. Если провайдер это поддерживает, то цикл можно поразворачивать.
... << RSDN@Home 1.2.0 alpha rev. 677>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[2]: копирование данных
От: Аноним  
Дата: 12.09.07 11:24
Оценка:
Здравствуйте, IqwertyI, Вы писали:

_>>По 100Мбитной локалке 1млн. записей перегоняется за 18мин, сколько это будет на 128К даже считать не хочу .

_>>Понимаю, код кривой, и никуда не годится... подскажите как его сделать не таким кривым. Интересует повышение
_>>скорости и надежности работы. Использовать транзакции ? А как ? Для каждого INSERTa свою транзакцию ? Или одну для
_>>всех INSERTов ? Если можно киньте примеры кода, или хоть подскажите в каком направлении копать. Заранее спасибо.
II>Мне кажется проблема в выполнении 1млн Insert-ов, надо от этого уходить использованием xml или еще каких нибудь структур данных, хотя я не знаком с возможностями MySql. И конечно надо использовать транзакции:

II>MySqlConnection rem_conn = GetConnection(false);

II>rem_conn.Open();
II>MySqlTransaction tr = rem_conn.BeginTransaction();
II>MySqlCommand cmd_ = new MySqlCommand("", rem_conn);
II>...
II>tr.Commit();

Т.е скидывать данные в xml-файл, передавать его по сетке, а из него уже вставлять на серваке ?
Re[2]: копирование данных
От: vitalik_4  
Дата: 12.09.07 11:34
Оценка:
Здравствуйте, Sinclair, Вы писали:

S>Во-первых, возьми карандащ, бумагу, и четыре миллиона раз напиши "я никогда не буду передавать параметры в SQL стейтмент при помощи конкатенации". Изучи, как правильно передавать параметры.


А как надо ? через MySQLParameter ?

S>Во-вторых, срочно изучи как пользоваться using.


А с using что не так ?

S>В третьих, в цикле нужно делать как можно меньше работы. В частности, вывод на консоль отжирает и без того ценное время. Хочется следить за прогрессом — выводи count раз в секунду.


С этим понятно, это просто временно — на этапе тестирования. В дальнейшем это вообще будет сервис.
Re[3]: копирование данных
От: Sinclair Россия https://github.com/evilguest/
Дата: 12.09.07 12:22
Оценка:
Здравствуйте, vitalik_4, Вы писали:

_>Здравствуйте, Sinclair, Вы писали:


S>>Во-первых, возьми карандащ, бумагу, и четыре миллиона раз напиши "я никогда не буду передавать параметры в SQL стейтмент при помощи конкатенации". Изучи, как правильно передавать параметры.


_>А как надо ? через MySQLParameter ?

да.
S>>Во-вторых, срочно изучи как пользоваться using.

_>А с using что не так ?

ты его не используешь.
_>С этим понятно, это просто временно — на этапе тестирования. В дальнейшем это вообще будет сервис.
Не стоит вставлять тормозящий код в тест быстродействия.
... << RSDN@Home 1.2.0 alpha rev. 677>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[4]: копирование данных
От: vitalik_4  
Дата: 13.09.07 07:09
Оценка: +1
_>>Здравствуйте, Sinclair, Вы писали:

S>>>Во-первых, возьми карандащ, бумагу, и четыре миллиона раз напиши "я никогда не буду передавать параметры в SQL стейтмент при помощи конкатенации". Изучи, как правильно передавать параметры.

_>>А как надо ? через MySQLParameter ?
S>да.
[c#]
...
cmd_.CommandText = "INSERT INTO datagps_1(Mobitel_ID) VALUES(@Mobitel_ID)";
cmd_.Connection = conn1;

cmd_.Parameters.Add(new MySqlParameter("@Mobitel_ID", MySqlDbType.Int64));
...

conn.Open();
conn1.Open();

MySqlDataReader reader = cmd.ExecuteReader();
while (reader.Read())
{
cmd_.Parameters["@Mobitel_ID"].Value = reader["Mobitel_ID"];
cmd_.ExecuteNonQuery();
}
...
c
так ?
Re[5]: копирование данных
От: brainunit  
Дата: 13.09.07 11:11
Оценка:
Здравствуйте, vitalik_4, Вы писали:

_>>>Здравствуйте, Sinclair, Вы писали:


S>>>>Во-первых, возьми карандащ, бумагу, и четыре миллиона раз напиши "я никогда не буду передавать параметры в SQL стейтмент при помощи конкатенации". Изучи, как правильно передавать параметры.

_>>>А как надо ? через MySQLParameter ?
S>>да.
_>[c#]
_> ...
_> cmd_.CommandText = "INSERT INTO datagps_1(Mobitel_ID) VALUES(@Mobitel_ID)";
_> cmd_.Connection = conn1;

_> cmd_.Parameters.Add(new MySqlParameter("@Mobitel_ID", MySqlDbType.Int64));

_> ...

_> conn.Open();

_> conn1.Open();

_> MySqlDataReader reader = cmd.ExecuteReader();

_> while (reader.Read())
_> {
_> cmd_.Parameters["@Mobitel_ID"].Value = reader["Mobitel_ID"];
_> cmd_.ExecuteNonQuery();
_> }
_> ...
_>c
_>так ?

Надо ещё сделать cmd.Prepare(). Это значительно ускорит вставку данных. Дата ридер обязательно надо оборачивать в using!
cmd.Prepare();
using (MySqlDataReader reader = cmd.ExecuteReader())
  while (reader.Read())
  {        
    cmd_.Parameters["@Mobitel_ID"].Value = reader["Mobitel_ID"];
    cmd_.ExecuteNonQuery();  
  }



И ещё — если ты используешь провайдер MySQLDirect .NET, (а не MySQL Connector/NET), то в нём есть специальный класс для быстрой вставки большого количества данных — MySqlLoader.
Re[2]: копирование данных
От: brainunit  
Дата: 13.09.07 11:23
Оценка:
Здравствуйте, IqwertyI, Вы писали:

II>Здравствуйте, vitalik_4, Вы писали:


_>>По 100Мбитной локалке 1млн. записей перегоняется за 18мин, сколько это будет на 128К даже считать не хочу .

_>>Понимаю, код кривой, и никуда не годится... подскажите как его сделать не таким кривым. Интересует повышение
_>>скорости и надежности работы. Использовать транзакции ? А как ? Для каждого INSERTa свою транзакцию ? Или одну для
_>>всех INSERTов ? Если можно киньте примеры кода, или хоть подскажите в каком направлении копать. Заранее спасибо.
II>Мне кажется проблема в выполнении 1млн Insert-ов, надо от этого уходить использованием xml или еще каких нибудь структур данных, хотя я не знаком с возможностями MySql. И конечно надо использовать транзакции:

II>MySqlConnection rem_conn = GetConnection(false);

II>rem_conn.Open();
II>MySqlTransaction tr = rem_conn.BeginTransaction();
II>MySqlCommand cmd_ = new MySqlCommand("", rem_conn);
II>...
II>tr.Commit();

Использование транзакций — это штука хорошая, но быстродействия не добавит, как и использование транзакционного storage engine InnoDB. Для максимальной скорости стоит использовать MyISAM. Я бы даже сделал так (псевдокод на SQL):
SET FOREIGN_KEY_CHECKS=0;
ALTER TABLE <table> DISABLE KEYS;
LOCK TABLES <table> WRITE;

<insert>

UNLOCK TABLES;
ALTER TABLE <table> ENABLE KEYS;
SET FOREIGN_KEY_CHECKS=1;
Re[6]: копирование данных
От: vitalik_4  
Дата: 13.09.07 13:27
Оценка:
Здравствуйте, brainunit, Вы писали:

S>>>>>Во-первых, возьми карандащ, бумагу, и четыре миллиона раз напиши "я никогда не буду передавать параметры в SQL стейтмент при помощи конкатенации". Изучи, как правильно передавать параметры.



B>Надо ещё сделать cmd.Prepare(). Это значительно ускорит вставку данных. Дата ридер обязательно надо оборачивать в using!

B>[code]
B>cmd.Prepare();
B>using (MySqlDataReader reader = cmd.ExecuteReader())
B> while (reader.Read())
B> {
B> cmd_.Parameters["@Mobitel_ID"].Value = reader["Mobitel_ID"];
B> cmd_.ExecuteNonQuery();
B> }

А, вот оно что, а то я и смотрю, что у меня через параметры делается на 5мин. дольше чем при формировании запроса с помощью конкатенации. Спасибо что просвятили. А что using дает ?

B>И ещё — если ты используешь провайдер MySQLDirect .NET, (а не MySQL Connector/NET), то в нём есть специальный класс для быстрой вставки большого количества данных — MySqlLoader.


Не, я другой использую. Там такого нет.
Re[7]: копирование данных
От: Sinclair Россия https://github.com/evilguest/
Дата: 14.09.07 03:40
Оценка:
Здравствуйте, vitalik_4, Вы писали:

_>А, вот оно что, а то я и смотрю, что у меня через параметры делается на 5мин. дольше чем при формировании запроса с помощью конкатенации. Спасибо что просвятили. А что using дает ?

RTFM. Он автоматически закрывает IDisposable-ресурс. Сокращенная запись для try... finally.
... << RSDN@Home 1.2.0 alpha rev. 677>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[2]: копирование данных
От: vitalik_4  
Дата: 14.09.07 07:13
Оценка:
Здравствуйте, Sinclair, Вы писали:

S>Здравствуйте, vitalik_4, Вы писали:


S>Во-первых, возьми карандащ, бумагу, и четыре миллиона раз напиши "я никогда не буду передавать параметры в SQL стейтмент при помощи конкатенации". Изучи, как правильно передавать параметры.


А медленней кстати получается через параметры. Через конкатенацию копировалось за 18 мин, а через параметры за 22. Тем более я собираюсь делать через транзакции (за одну транзакцию делать несколько
ИНСЕРТОВ) типа INSERT INTO ... VALUES ( (<один набор знач.>), (<др набор знач.>)...); т.е формировать
INSERT на каждой итерации цикла while (reader.Read()), а выполнять не на каждой. А параметры — то подставляются только при выполнении запроса...

S>В четвертых, почитай документацию по своему провайдеру, и выясни, можно ли использовать batch — т.е. несколько SQL команд в одном запросе. Если провайдер это поддерживает, то цикл можно поразворачивать.


А можно примерчик ? Или хоть ссылочку на примерчик.
Re[8]: копирование данных
От: Mr.Cat  
Дата: 14.09.07 08:53
Оценка:
А в MySQL есть связанные сервера?
Чтобы можно было писать что-то вроде select * from db1.table1 into srv2.db2.table2
Re[9]: копирование данных
От: Sinclair Россия https://github.com/evilguest/
Дата: 14.09.07 09:15
Оценка:
Здравствуйте, Mr.Cat, Вы писали:

MC>А в MySQL есть связанные сервера?

MC>Чтобы можно было писать что-то вроде select * from db1.table1 into srv2.db2.table2
Представления не имею. Но подозреваю, что поиск в Google даст нужный ответ секунд через 40.
... << RSDN@Home 1.2.0 alpha rev. 677>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.