Tsvetov/analys_users
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Folders and files
Name | Name | Last commit message | Last commit date | |
---|---|---|---|---|
Repository files navigation
Это приложение для django(1.8). Идея такая: 1. Денормализовать исходные данные. Исходная таблица: IpTable: user_id ip_address date Таблица денормализации: UserIp: user_id ips users Где ips - это массив ip пользователя, а users - это рекурсивная связь Многие-ко-многим, куда сохраняем уже посчитанные отношения между пользователями 2. Синхронизировать данные в бд с помощью тригера SQL( текcт триггрера находиться в миграции 0002_auto_20150818_2011.py) При записи(INSERT) новой пары IpTable.user_id-IpTable.ip_address в таблицу UserIp записывается информация о паре user-ips(если такой еще нет). 3. Поставить индекс на колонку UserIp.user_id. ORM django ставит индекс на колонку первичного ключа по умолчанию, однако это b-дерево, а нужно Hash, поэтому ставим hash-индекс в миграции (0002_auto_20150818_2011.py) 4. После вышеупомянутых манипуляций,вытащить из базы нужные нам данные и посчитать результат не состовляет труда. 1. Проверяем рекурсивную связь users => если у пользователей есть эта связь, то они взаимосвязаны. 2. Берем списоки ip пользователей, преобразуем во множество и пересекаем, если пересечение <= 1 следовательно пользователи не взаимосвязаны. 3. Множество получившийся из шага 2 мы преобразуем с помощью функции imap(аналог map), в список подсетей, затем во множество подсетей, если это размер множества <= 1 следовательно, пользователи не взаимосвязаны. 4. Если условные операторы 2 и 3 шага не сработали, следовательно пользователи взаимосвязаны(перед тем как вернуть True, нужно записать связь users) Примерный результат тестов: 1000 user_id ~ 0.74 ms 10000 user_id ~1.3 ms 1000000 user_id ~2.5 ms 10000000 user_id ~2.7 ms Надо добавить что количество user - это колличество уникальных пользователей. Т.Е. записей в исходной таблице было в ~3~4 раза больше. ТЕсты проводились как на положительный так и на отрицательный результат. TODO(возможные улучшения): 1. Передавать данные по json(решение, передавать данные в сессии при редиректе, наверное не самое лучшее) и вообще переработать интерфейс. У меня было несколько вариантов решений. Остановился на нем - потому как: - из всех моих решений максимальная скорость. - при увеличении данных скорость практически не меняется. - простота кода. Минусы данного подхода: - перекладывая часть расчетов на момент записи исходных данных в таблицу(trigger), мы можем потерять в скорости сервисов(которые эти данные пишут) - Много SQL-кода. - Может быть такая ситуация - когда у одного пользователя раздувается список ip(их всего может быть не больше ~2000000 для класса С). При этом скорость работы у таких пользователей проседала раза в 5-6(что на самом деле не очень критично, при таком увеличении данных). Для запуска, нужно прописать в settings.install_apps название приложения analys_users, и прописать urls: url(r'^', include('analys_users.urls'))
About
analys_users
Resources
Stars
Watchers
Forks
Releases
No releases published
Packages 0
No packages published