2010-05-17 2 views
3

Этот вопрос может показаться слишком простым для некоторых, но, пожалуйста, не стесняйтесь, прошло некоторое время, так как я занимался достойным программированием базы данных.Применение итеративного алгоритма к набору строк из базы данных

У меня есть алгоритм, который мне нужно запрограммировать в PHP/MySQL для работы на веб-сайте. Он выполняет некоторые вычисления итеративно на массиве объектов (он оценивает объекты на основе их свойств). На каждой итерации алгоритм проходит через всю коллекцию пару раз, обращаясь к различным данным из разных мест всей коллекции. Алгоритму необходимо выполнить несколько сот итераций. Массив поступает из базы данных.

Простым решением, которое я вижу, является получение результатов запроса к базе данных и создание объекта для каждой строки запроса, помещение объектов в массив и передача массива в мой алгоритм.

Тем не менее, я заинтересован в эффективности такого решения, когда мне приходится работать с массивом из нескольких тысяч элементов, потому что то, что я делаю, по существу отражает результаты запроса в память.

С другой стороны, запрос базы данных пару раз на каждой итерации алгоритма также кажется неправильным.

Итак, мой вопрос: какое правильное архитектурное решение для такой проблемы? Можно ли отразить результаты запроса в памяти? Если нет, это лучший способ работать с результатами запроса в таком алгоритме?

Спасибо!

ОБНОВЛЕНИЕ: Ближайшая проблема, о которой я могу думать, - ранжирование результатов поиска поисковой системой - мне нужно сделать что-то похожее на это. Каждый результат представляется как строка базы данных, и все результаты набора рассматриваются при вычислении ранга.

ответ

1

Память кажется наилучшим способом - если вы можете масштабироваться, чтобы встретить ее. В противном случае вам придется пересмотреть свой алгоритм, чтобы, возможно, использовать подход типа «разделение» и «завоевать» - сделать что-то вроде сортировки слияния.

1

Это действительно зависит от ситуации. Это, вероятно, редко требуется, чтобы делать такую ​​вещь, но очень сложно сказать, основываясь на информации, которую вы дали.

Постарайтесь изолировать данные как можно больше. Например, если вам нужно выполнить какое-то независимое действие над данными, которые не имеют зависимостей между итерациями цикла, вы можете написать запрос для обновления затронутых строк, а не для их загрузки в память, только для их записи ,

Короче говоря, это, вероятно, можно избежать, но это трудно сказать, пока вы не дадите нам больше информации :)

+0

Извините, мне сложно дать больше информации, не написав подробное описание, которое никто не будет читать :) Ближайшая проблема, о которой я могу думать, - ранжировать результаты поиска поисковой системой - мне нужно сделать что-то подобное этому. Каждый результат представляется как строка базы данных, и все результаты набора рассматриваются при вычислении ранга. – Corvin

+0

Даже для примера, который вы указали, вы не будете сразу загружать все результаты в память. Вы должны работать на меньших наборах данных и выполнять процесс итеративно, если вы беспокоитесь о том, чтобы перегрузить систему. –

0

является вычисление одного объекта зависит от другого, или все они независимы? Если они независимы, вы можете загрузить только небольшое количество строк из базы данных, преобразуя их в объекты по мере их описания. Затем запустите сотни итераций на них, а затем выведите результат для этого блока. Затем переходите к следующему блоку элементов.

Это уменьшает использование памяти, поскольку вы используете только небольшое количество элементов, а не весь набор данных, и избегаете запуска нескольких запросов в базе данных.

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

+0

Все они зависимы, поэтому я не вижу способ работать с небольшим подмножеством – Corvin

1

Если вы выполняете запрос к базе данных, когда результаты возвращаются, они уже «зеркалируются в память». Когда вы получаете свои результаты с помощью mysql_fetch_assoc (или equiv), у вас есть ваша копия. Просто используйте это как кеш.

+0

Действительно ли это так? Вы хотите сказать, что «SELECT * FROM xxx» в таблице со 10000 строками с блоками ~ 50K в каждой записи будет chomp 500Mb памяти для одного запроса? Я думал, что PHP лучше, чем это ... – Corvin

2

Не забывайте, преждевременная оптимизация - это корень всего зла. Дайте ему выстрел, копируя все в память. Если это использует слишком много mem, то оптимизируйте для памяти.

+1

Я думаю, что цитата слишком высока. Я думаю, что было бы неплохо планировать расширение, делая разумные проектные решения, которые не так легко изменить, как только они будут реализованы. Беспокойство по поводу использования 4-байтового числа по сравнению с механизмом смещения битов и добавлением для выполнения одного и того же представления данных с 1-байтовым номером более подходит для цитаты (учтите, что этот комментарий не сопровождал нисходящее движение). –

+0

Хорошо, тогда он должен быть инженером и провести оценку стоимости количества строк ожидаемых данных, раз каждого размера данных в строке и определить приблизительную потребность в памяти для профиля процедуры. Если это число больше, чем доступный объем памяти, минус некоторые разумные накладные расходы, то он должен беспокоиться о конструировании для компиляции доступа к памяти/запросу. Я обнаружил, что в 99% случаев быстрее всего делать то, что я сказал в первую очередь, и пусть ошибка из памяти говорит вам, что вам нужно оптимизировать память. – Zak

+1

Да, справедливо. Я не думаю, что несколько тысяч записей слишком много, чтобы разобраться, если все сделано правильно ... просто, что я устал от клише :) –

0

Возможно также писать запросы на ранжирование с помощью MySQL, вам просто нужно немного поиграть с пользовательскими переменными. Если вы предоставите некоторые входные данные и результат, который вы собираетесь достичь, ответы будут более подробными.

+0

Это тоже вариант, спасибо. Интересно, будут ли хранимые процедуры делать трюк. – Corvin

0

Вы можете использовать задание cron, чтобы сделать свой рейтинг, сказать один раз в день, час или все, что вам нужно, и затем сохраните ранжирование позиций в поле в своей строке?

Таким образом, когда вы вызываете свои ряды, вы можете просто заказать их по полю ранжирования.

+0

Спасибо, но это не вариант - возможно слишком много комбинаций. Это похоже на поисковую систему - вы не сможете кэшировать все возможные поисковые запросы – Corvin

Смежные вопросы