Ну хорошо, fgets станет в полтора раза быстрее чем он же с параметром. Всё равно он будет заметно медленнее, чем stream_get_line. Я натравил ваш скрипт на свою "Войну и мир" -- 63.530905008316 против 43.740499019623. Так что вывод вы сделали неправильный.
у меня время выполнения файла на 3470 строк в этом случае 108.04760408401 Код (Text): $handle = fopen("cross.txt", "r"); while(($fle = fgetcsv($handle, 100000000,",","'"))!== FALSE){ $query = mysql_query("INSERT INTO `crossnumbers` (ARL_ART_ID, ARL_SEARCH_NUMBER, ARL_BRA_ID, ARL_DISPLAY_NR) VALUES ('$fle[0]', '$fle[1]', '$fle[3]', '$fle[4]')"); } а в этом 114.80180907249 Код (Text): $handle = fopen("cross.txt", "r"); while (!feof($handle)) { $line = stream_get_line($handle, 0, "\r\n"); $fle = str_getcsv($line, ",", "''", "\r\n"); $query = mysql_query("INSERT INTO crossnumbers (ARL_ART_ID, ARL_SEARCH_NUMBER, ARL_BRA_ID, ARL_DISPLAY_NR) VALUES ('$fle[0]', '$fle[1]', '$fle[3]', '$fle[4]')"); }
Если 108 это секунды, то у Вас движок настроен "нехорошо". Решение: использовать транзакции, по 1000-3000 записей на одну транзакцию. Для mySQL скорость записи в режиме транзакции должна быть несолько тысяч записей в секунду. Если нет, то смотреть настройки движка.
делаю так Код (Text): $handle = fopen("cross.txt", "r"); while (!feof($handle)) { $line = stream_get_line($handle, 0, "\r\n"); $fle = str_getcsv($line, ",", "''", "\r\n"); $query = mysql_query("INSERT INTO crossnumbers (ARL_ART_ID, ARL_SEARCH_NUMBER, ARL_BRA_ID, ARL_DISPLAY_NR) VALUES ('$fle[0]', '$fle[1]', '$fle[3]', '$fle[4]')"); } и выдаёт ошибку вот такую 1064: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'BMES4204', '134', 'BM-ES-4204', 'MOOG')' at line 1 Добавлено спустя 1 минуту 19 секунд: а как использовать то что вы мне советуете? можете примерчик кинуть? и как настроить движок по другому и что именно настраивать?
Мои данные (Ваш тест): - Total: 12118735 lines in 22.5143 sec (stream, как есть) - Total: 12119553 lines in 57.3517 sec (fgets, как есть) - Total: 12119553 lines in 19.5919 sec (fgets без параметра) - Total: 12119553 lines in 28.3024 sec (fgets без параметра, но с rtrim) - Total: 0 lines in 19.6603 sec (stream, как есть и без подсчёта времени каждые 100000) - Total: 0 lines in 17.1730 sec (fgets без параметра и без подсчёта времени каждые 100000) - Total: 0 lines in 27.2675 sec (fgets без параметра с rtrim и без подсчёта времени каждые 100000) К диску обращения практически нет (файл весть в буфере Win7, я так понимаю). Загрузка проца i7 - "стандартные" 12%. Как-то так... Добавлено спустя 6 минут 16 секунд: 1) Изучите доку по транзакциям. 2) затем в цикле каждую 1000 записей commit и запуск снова 1) Читать доку по движку, который Вы используете. 2) Если Вам это не нужно по работе (часто), то лучше не лезть и использовать транзакции - так много проще.
Федеральная информационная адресная система. грубо говоря это замена КЛАДРа. более полная база, лучше структура, обновления, форматы хранения и т.д.
примерчик? START TRANSACTION; INSERT INTO tbl_name (a,b,c) VALUES(1,2,3),(4,5,6),(7,8,9),...,(10001,10002, 10003); COMMIT;
Во-во, такая непонятнка частенько бывает INSERT с множественным VALUES и так выполняется атомарно, т.е. транзакционные рамки не нужны. Вот молодёжь обленилась ныне, даже одну извилину лень напрячь! Модифицируем Ваш вариант, что-то вроде: Код (Text): $handle = fopen("cross.txt", "r"); $i = 0; mysql_query('begin transaction'); while(($fle = fgetcsv($handle, 0,",","'"))!== FALSE){ $query = mysql_query("INSERT INTO `crossnumbers` (ARL_ART_ID, ARL_SEARCH_NUMBER, ARL_BRA_ID, ARL_DISPLAY_NR) VALUES ('$fle[0]', '$fle[1]', '$fle[3]', '$fle[4]')"); $i++; if($i > 999) { mysql_query('commit') mysql_query('begin transaction'); $i = 0; } } mysql_query('commit') Добавлено спустя 3 минуты 19 секунд: Но вообще-то igordata прав в том, что ещё лучше, чем транзакции, использовать множественные значения values() для пакетного добавления записей - будет ещё быстрее.
хз насчёт транзакций. если мне надо было всунуть базу из файла, то я б залочил таблицы. но такую операцию конечно нельзя делать часто. Либо тогда надо делать всё по-уму на транзакциях,но прочие выборки должны учитывать эти транзакции и выбирать себе строки в случае необходимости с залочкой тоже. ну это просто пример...я так понял, что транзакции нужны как раз для того, чтобы стопорнуть, потом порциями фигачить с перерывами на чтение новой порции из файла. А атомарные операции рулят. С ними спокойно. Иногда проще пожертвовать частью логики и сделать типа как INSERT ON DUPLICATE KEY UPDATE и после выборку, чем делать выборку и на фейле инсертить, т.к. придётся лочить таблицу во втором случае.
если делать так, то выдаёт ошибку Out of memory а если так Код (Text): $handle = fopen("TOF_ART_LOOKUP.txt", "r"); mysql_query('begin transaction'); $i = 0; while (!feof($handle)) { $line = stream_get_line($handle, 0, "\r\n"); $fle = str_getcsv($line, ",", "''", "\r\n"); //грузим номера в таблицу БД $query = mysql_query("INSERT INTO `crossnumbers` (`ARL_ART_ID`, `ARL_SEARCH_NUMBER`, `ARL_BRA_ID`, `ARL_DISPLAY_NR`) VALUES ('$fle[0]', '$fle[1]', '$fle[3]', '$fle[4]')"); $i++; if($i > 999) { mysql_query('commit'); mysql_query('begin transaction'); $i = 0; } mysql_query('commit'); } то заливает в базу только 13701 строк и прекращается выполнение скрипта, ошибок не выдаёт
Учите матчасть и всё будет работать. п.с. Никто за Вас делать не будет здесь, - могут только подсказать. И то не каждый раз.
я знаю, и не прошу чтоб кто-то что-то за меня делал, просто не всегда понятны подсказки которые дают ... я учусь, маловато ещё знаю, но по мере того как сталкиваюсь с проблемой, разбираю и учу эту тему, но не всегда всё наглядно понятно. спасибо за помощь. Пока что пошёл я другим путём, минуя файл. Выгружаю напрямую из одной БД в другую.. что-то файл мне не дался. Но хочу всётаки разобрать эту тему с файлом...
Простой синтетический Тест скорости добавления записей в БД. mySQL 5.5, InnoDB; PHP, mysqli Таблица: Код (Text): CREATE TABLE `ttt` ( `id` int(11) NOT NULL AUTO_INCREMENT, `text` varchar(255) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB CHARSET=cp1251 В тест artoodetoo (см.выше) был добавлен кусок: Код (Text): $d->query("insert into ttt (text) values('{$d->real_escape_string($line)}')"); if(! ($i % 1000)) { $d->query('commit'); $d->query('start transaction'); } Результаты для (innodb_flush_log_at_trx_commit = 2): Код (Text): - Total: 1000000 lines in 2.0179 sec (stream_get_line, простое чтение) - Total: 1000000 lines in 108.3384 sec (+mysqli, без транзакций /для сравнения/) - Total: 1000000 lines in 74.4685 sec (+mysqli, 100 зап/транзакцию) - Total: 1000000 lines in 71.3403 sec (+mysqli, 1000 зап/транзакцию) - Total: 1000000 lines in 68.9027 sec (+mysqli, 10000 зап/транзакцию) - Total: 1000000 lines in 41.9548 sec (+mysqli, 100 значений VALUES, без транзакций) - Total: 1000000 lines in 29.8311 sec (+mysqli, 1000 значений VALUES, без транзакций) Итого: Множественный VALUES где-то в ~2 раза быстрее. Позволяет добавлять до 33 тысяч зап/сек. Результаты для (innodb_flush_log_at_trx_commit = 1 /default): Код (Text): - Total: 1000 lines in 50.3604 sec (+mysqli, без транзакций /т.е. ~50000 сек для 1 млн.зап./) - Total: 1000000 lines in 724.3489 sec (+mysqli, 100 зап/транзакцию) - Total: 1000000 lines in 147.4507 sec (+mysqli, 1000 зап/транзакцию) - Total: 1000000 lines in 78.0385 sec (+mysqli, 10000 зап/транзакцию) - Total: 1000000 lines in 600.8820 sec (+mysqli, 100 значений VALUES, без транзакций) - Total: 1000000 lines in 90.5256 sec (+mysqli, 1000 значений VALUES, без транзакций) - Total: 1000000 lines in 35.5952 sec (+mysqli, 10000 значений VALUES, без транзакций) Итого: Множественный VALUES где-то в ~2 раза быстрее. Кроме того, пакетное добавление 10000 записей в ~2.5 раза быстрее, чем в 1000 зап, и позволяет добавлять до 28 тысяч зап/сек. Как-то так... Конечно, ничего даром не даётся - например, чем больше пакет, тем больше требуется RAM.
Всё "стандартно": Win7 x64, Intel i7-2600K, HD WD green 2T, RAM 8G. Нагрузка на проц ~12%. Диск самое тормозное место, - хорошо видно во втором тесте. п.с. Естественно, число записей в каждом конкретном случае будет разное. Например, если добавлять x32 число, то скорость в записях/сек может быть намного больше. А если текст в мегабайт, то и 20 з/сек может не быть. Плюс движок, +кодировка, +индексы и т.п. Железо конечно тоже влияет.
а я вообще не понимаю о чем этот топик. если можешь сдампить базу то начерта тебе скрипт. если надо делать регулярно, то опять-таки это делается средствами самих серверов БД... хзхз. Но проблема есть, и её тут принято решать не задавая вопросов аначерта и зачемтебеэто.
да, не пойму в чём затык .. переделал этот файл по другому, попробую без кавычек, а то они реально большую нагрузку похоже дают.. и ещё я при загрузке в БД сразу пытался присваивать некоторым значениям другие.. вот и от этого нагрузка ещё шла, прийдётся разделить процессы эти не, с этим норм.. Код (Text): set_time_limit(0);