php, большой массив, как с ним работать?

12
humbert
На сайте с 16.03.2006
Offline
532
6817

Есть большой массив, примерно 640.000 строк, если в файле, то 15Мб информации.

Как работать с таким массивом не перегружая сервер? В основном надо рандомно выбирать данные из него, порядка 2.000 строк за раз, при этом удаляя то, что было выбрано, т.е. уменьшая сам массив.

Парсинг прайс-листов, наполнение интернет-магазина товаром. (https://humbert.ru) Любая CMS (Битрикс, OpenCart, Prestashop и даже Woo Commerce )
T.R.O.N
На сайте с 18.05.2004
Offline
314
#1

humbert,

при всей моей нелюбви, должен сказать, что здесь, как-раз, задача для мускула. Файл перегнать в БД и пользовать.

Если есть желание остаться с файлом, то не мудрить, а читать файл построчно, одновременно записывая новый (без удаленных строк). Работать будет чуть медленнее, но зато не перегружая сервак.

От воздержания пока никто не умер. Хотя никто и не родился! Prototype.js был написан теми, кто не знает JavaScript, для тех, кто не знает JavaScript (Richard Cornford)
Netsp
На сайте с 17.01.2007
Offline
49
#2

Загнать этот массив в mysql базу.

humbert
На сайте с 16.03.2006
Offline
532
#3

Проблема в том, что таких массивов может быть и 100 и 1000

P.s. в мускул загонял, вес одного массива 20мб в таблице.

akaplenko
На сайте с 09.09.2009
Offline
48
#4
humbert:
в мускул загонял, вес одного массива 20мб в таблице.

Критичен размер базы?

На самом деле есть потеря в дисковом пространстве при размещении подобной информации в базе.

Но при работе с массивами вы сталкиваетесь с некоторыми сложностями, а именно:

- во первых этой громадиной в памяти работать не совсем удобно.

- быстрое удаление из массива в php при таких размерах становится достаточно нетривиальной задачей.

Так что смотрите все-таки в сторону БД. Я обрабатываю таблицы с количеством записей в 4-5 млн. (основная операция - выборка случайных строк из таблицы). При желании можно воспользоваться стандартной функцией MySQL - rand (ORDER BY RAND). Ну или по старинке, ручками по id-шникам.

Пы.Сы. Текст перемешиваешь , да ? ;-)

[Удален]
#5

humbert, я бы прошелся по файлу и "заметил" начала строк и их длину, создал индексный файл, он бы получился под 100кб отсилы я думаю и юзал его для своих задач. открыть файл, оффсетнуть в место и считать пусть даже 5000 байт - милисекунды, при этом не надо насиловать бд, память, проц, файловую систему.

по похожему принципу работает моя одна штучка - гео бибилотека, так у нее скорость разрешения страны для IP - 40 000 ip в СЕКУНДУ на моем ноутбуке. ни один мускуль сервер столько не сделает, поверьте ;) проверял, даже рядом не стоит.

когда я ее написал, была самая быстрая библиотека на питоне (или перле, точно не помню), там была скорость 5000 в секунду)

edogs software
На сайте с 15.12.2005
Offline
775
#6
akaplenko:
Так что смотрите все-таки в сторону БД. Я обрабатываю таблицы с количеством записей в 4-5 млн. (основная операция - выборка случайных строк из таблицы). При желании можно воспользоваться стандартной функцией MySQL - rand (ORDER BY RAND).

Очень странно. order by rand() жутко тормозная штука, которая при работе выбирает все записи из таблицы, потом их сортирует и часть (нужную) возвращает. Использовать ее при большом количестве записей это садизм. А Вы при4-5млн записей ее используете?

humbert:
Есть большой массив, примерно 640.000 строк, если в файле, то 15Мб информации.

Как работать с таким массивом не перегружая сервер? В основном надо рандомно выбирать данные из него, порядка 2.000 строк за раз, при этом удаляя то, что было выбрано, т.е. уменьшая сам массив.

1) Если строки ограниченного и небольшого размера, то можно упорядочить структуру, конвертнуть файл в файл со строками одного размера и с ними работать.

2) Загнать все-таки в базу. Неужели так велика разница между 15Мб в файлах и 20Мб в базе? Если еще важна скорость, то memory table могут неслабо помочь.

3) Вариант 2, только в sqllite загнать, что бы с мускулом не городить и с файлами по сути работать.

4) Можно сделать как предложил bearmen, его вариант это по сути создание своей простой БД, единственное преимущество которого в простоте. Но для простоты опять же годится sqllite

Разработка крупных и средних проектов. Можно с криптой. Разумные цены. Хорошее качество. Адекватный подход. Продаем lenovo legion в спб, дешевле магазинов, новые, запечатанные. Есть разные. skype: edogssoft
[Удален]
#7
edogs:
Очень странно. order by rand() жутко тормозная штука, которая при работе выбирает все записи из таблицы, потом их сортирует и часть (нужную) возвращает. Использовать ее при большом количестве записей это садизм. А Вы при4-5млн записей ее используете?

тоже заметил да не стал коментировать)

причем сортировка (всегда? вопрос к edogs. я не знаю метода сортировать по рандому без темп тейбла и order by rand(), когда приходится - ухищряюсь через селфжойн айди таблички сортированой, при больших таблицах конечно заметно, но всеже не order * by rand ))) чере темп тейбл

humbert
На сайте с 16.03.2006
Offline
532
#8

bearman, спасибо, об этом думал уже (индексный файл). Пока остановился на другом решении, применил БД.

[Удален]
#9

humbert, ну я ваших затей не знаю )))

может вам миллион хитов в час надо :D тогда такой метод имеет право на жизнь )))))))

edogs software
На сайте с 15.12.2005
Offline
775
#10
bearman:
причем сортировка (всегда? вопрос к edogs. я не знаю метода сортировать по рандому без темп тейбла и order by rand(), когда приходится - ухищряюсь через селфжойн айди таблички сортированой, при больших таблицах конечно заметно, но всеже не order * by rand ))) чере темп тейбл

Зависит от кол-ва нужных Вам случайных значений.

1) Если нужно немного - типа пара, то классическим способом, при не слишком дырявой базе по ИД считается (утрированно).

$max="select max(id)"; $id=mt_rand(1,$max); $res="select * from table where id>$id limit 1";

и так нужное количество раз

2) Если нужно побольше (допустим 200) и база чуть более дырява (допустим треть отсутствует), то опять же при не слишком дырявой БД вполне работает нечто вроде первого же способа, только сначала генерим штук 400 рандомных ИД (в php тупо mt_rand-ом например), потом делаем один запрос на выборку данных по этим ИД (select * from table where id in (1,525,252...), если недостаточно выбралось (попали много раз на дырки), то делаем еще запрос.

3) Ну и если выборки достаточно частые, а апдейты редкие + ИД достаточно дырявые, то есть смысл завести таблицу соответствий "ИД_рандом <> ИД_Реальный". Где ИД_рандом будут значениями подряд идущими. Тогда будет отдельная, быстрая, недырявая таблица для выборки случайных значений (способом 2).

12

Авторизуйтесь или зарегистрируйтесь, чтобы оставить комментарий