Я разрабатываю приложение PHP для портала недвижимости, и у меня есть база данных MySQL с таблицей свойств. Эта таблица содержит около 500 000 строк и около 20 столбцов для объектов свойств. Предположим, что каждая функция является целым числом.
Примеры функций:
Мне нужно реализовать веб-страницу с панелью навигации в режиме реального времени с несколькими фильтрами. Идея состоит в том, что пользователи могут выбрать несколько функций, которые будут равны определенным значениям.
Например: 1-2 комнаты («1», «2»), здание 196x («6»), состояние среднее, хорошее или отличное («3», «4», «5»), в частности Город.
Ключевым требованием является возможность для пользователей видеть количество подходящих свойств рядом с каждым фильтром объектов с учетом выбранных фильтров.
Вот пример, как это должно выглядеть:
Rooms: 1[X], 2[X], 3[ ] (15000 more), 4[ ] (10000 more)
State: bad[ ] (1000 more), average[X], excellent[X]
Year: 1950[ ] (19000), 1960[ ] (20000), 1970[ ] (18000)
City: A[ ] (25000), B[ ] (18000), C[ ] (30000)
Price: <100000[ ] (20000), >100000[ ] (30000)
«[]» Обозначает пустой флажок (т.е. значение фильтра не выбрано), а «[X]» обозначает установленный флажок (т.е. значение фильтра выбрано).
Когда пользователь выбирает конкретное значение функции, скажем, City = London, цифры должны измениться, потому что они теперь ограничены предыдущими выборами:
Rooms: 1[X], 2[X], 3[ ] (5000 more), 4[ ] (5000 more)
State: bad (1000 more), average[X], excellent[X]
Year: 1950 (19000), 1960 (20000), 1970 (18000)
City: A[X], B (+4000), C (+3000)
Price: <100000 (5000), >100000 (6000)
Я попытался использовать следующий запрос SQL для каждой функции (X):
SELECT FeatureX, COUNT(*) AS num FROM properties WHERE selectedFeature1=Val1 AND selectedFeature2=Val2 ... AND selectedFeatureN=ValN GROUP BY featureX;
Однако набор этих запросов занимает несколько секунд, и мне нужно, чтобы это работало в режиме реального времени, т.е. <200 мс на бэкэнде.
Я пытался сохранить всю таблицу в общей памяти, но unserialize () массива с 500 000 записей также занимает около 1 с.
Единственное решение, которое я нашел, — это разработка отдельного приложения (например, в NodeJS), которое хранит данные в памяти в виде массива объектов и предоставляет API для основного приложения PHP. Это приложение обновляет данные из базы данных MySQL каждую минуту.
Однако, прежде чем приступить к реализации этого, я хотел бы спросить, есть ли какое-либо решение, основанное на самом MYSQL для такой задачи?
Если нет, то есть ли чисто PHP-решение?
У вас есть какие-то общие рекомендации, как подходить к решению этой задачи?
Не все может быть решено в базе данных.
Вы должны посмотреть на все 500К строк. Маловероятно, что какой-либо индекс поможет с более чем малой долей возможных запросов. Итак … Я предлагаю вам сохранить все данные в оперативной памяти и иметь некоторую быструю обработку (например, C ++) для выполнения всех из них.
Данные должны быть (в терминах MySQL) TINYINT UNSIGNED
что-то вроде char unsigned
, Возможно, данные могут быть сохранены в 20 байтов, один байт на функцию? Это всего 10 МБ в C ++, 30-100 МБ в MySQL, 400 МБ в PHP. MySQL может хранить данные в BINARY(20)
упростить выборку за счет вставки / обновления.
Используйте MySQL в качестве «источника правды» и периодически загружайте его в свой процессор (вы предложили 1 минуту и Node.js). Затем сфокусируйтесь на оптимизации счета.
Большинство языков в наши дни являются «интерпретирующими», следовательно, некоторые накладные расходы. C или C ++ являются двумя из немногих, которые работают на «машинном» уровне. Я почти уверен, что они могут выполнить вычисления 10M менее чем за 200 мс; Я сомневаюсь, что любой интерпретирующий язык может.
Других решений пока нет …