Пожалуйста подскажите. Надо прегнать по сетке (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();
По 100Мбитной локалке 1млн. записей перегоняется за 18мин, сколько это будет на 128К даже считать не хочу .
Понимаю, код кривой, и никуда не годится... подскажите как его сделать не таким кривым. Интересует повышение
скорости и надежности работы. Использовать транзакции ? А как ? Для каждого INSERTa свою транзакцию ? Или одну для
всех INSERTов ? Если можно киньте примеры кода, или хоть подскажите в каком направлении копать. Заранее спасибо.
Здравствуйте, vitalik_4, Вы писали:
_>По 100Мбитной локалке 1млн. записей перегоняется за 18мин, сколько это будет на 128К даже считать не хочу . _>Понимаю, код кривой, и никуда не годится... подскажите как его сделать не таким кривым. Интересует повышение _>скорости и надежности работы. Использовать транзакции ? А как ? Для каждого INSERTa свою транзакцию ? Или одну для _>всех INSERTов ? Если можно киньте примеры кода, или хоть подскажите в каком направлении копать. Заранее спасибо.
Мне кажется проблема в выполнении 1млн Insert-ов, надо от этого уходить использованием xml или еще каких нибудь структур данных, хотя я не знаком с возможностями MySql. И конечно надо использовать транзакции:
Во-первых, возьми карандащ, бумагу, и четыре миллиона раз напиши "я никогда не буду передавать параметры в 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-файл, передавать его по сетке, а из него уже вставлять на серваке ?
Здравствуйте, Sinclair, Вы писали:
S>Во-первых, возьми карандащ, бумагу, и четыре миллиона раз напиши "я никогда не буду передавать параметры в SQL стейтмент при помощи конкатенации". Изучи, как правильно передавать параметры.
А как надо ? через MySQLParameter ?
S>Во-вторых, срочно изучи как пользоваться using.
А с using что не так ?
S>В третьих, в цикле нужно делать как можно меньше работы. В частности, вывод на консоль отжирает и без того ценное время. Хочется следить за прогрессом — выводи count раз в секунду.
С этим понятно, это просто временно — на этапе тестирования. В дальнейшем это вообще будет сервис.
Здравствуйте, vitalik_4, Вы писали:
_>Здравствуйте, Sinclair, Вы писали:
S>>Во-первых, возьми карандащ, бумагу, и четыре миллиона раз напиши "я никогда не буду передавать параметры в SQL стейтмент при помощи конкатенации". Изучи, как правильно передавать параметры.
_>А как надо ? через MySQLParameter ?
да. S>>Во-вторых, срочно изучи как пользоваться using.
_>А с using что не так ?
ты его не используешь. _>С этим понятно, это просто временно — на этапе тестирования. В дальнейшем это вообще будет сервис.
Не стоит вставлять тормозящий код в тест быстродействия.
... << RSDN@Home 1.2.0 alpha rev. 677>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
_>>Здравствуйте, Sinclair, Вы писали:
S>>>Во-первых, возьми карандащ, бумагу, и четыре миллиона раз напиши "я никогда не буду передавать параметры в SQL стейтмент при помощи конкатенации". Изучи, как правильно передавать параметры. _>>А как надо ? через MySQLParameter ? S>да.
[c#]
...
cmd_.CommandText = "INSERT INTO datagps_1(Mobitel_ID) VALUES(@Mobitel_ID)";
cmd_.Connection = conn1;
Здравствуйте, 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.
Здравствуйте, 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;
Здравствуйте, 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.
Здравствуйте, vitalik_4, Вы писали:
_>А, вот оно что, а то я и смотрю, что у меня через параметры делается на 5мин. дольше чем при формировании запроса с помощью конкатенации. Спасибо что просвятили. А что using дает ?
RTFM. Он автоматически закрывает IDisposable-ресурс. Сокращенная запись для try... finally.
... << RSDN@Home 1.2.0 alpha rev. 677>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, Sinclair, Вы писали:
S>Здравствуйте, vitalik_4, Вы писали:
S>Во-первых, возьми карандащ, бумагу, и четыре миллиона раз напиши "я никогда не буду передавать параметры в SQL стейтмент при помощи конкатенации". Изучи, как правильно передавать параметры.
А медленней кстати получается через параметры. Через конкатенацию копировалось за 18 мин, а через параметры за 22. Тем более я собираюсь делать через транзакции (за одну транзакцию делать несколько
ИНСЕРТОВ) типа INSERT INTO ... VALUES ( (<один набор знач.>), (<др набор знач.>)...); т.е формировать
INSERT на каждой итерации цикла while (reader.Read()), а выполнять не на каждой. А параметры — то подставляются только при выполнении запроса...
S>В четвертых, почитай документацию по своему провайдеру, и выясни, можно ли использовать batch — т.е. несколько SQL команд в одном запросе. Если провайдер это поддерживает, то цикл можно поразворачивать.
А можно примерчик ? Или хоть ссылочку на примерчик.
Здравствуйте, Mr.Cat, Вы писали:
MC>А в MySQL есть связанные сервера? MC>Чтобы можно было писать что-то вроде select * from db1.table1 into srv2.db2.table2
Представления не имею. Но подозреваю, что поиск в Google даст нужный ответ секунд через 40.
... << RSDN@Home 1.2.0 alpha rev. 677>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.