Python самый быстрый способ найти значения в больших данных - PullRequest
0 голосов
/ 29 марта 2012

У меня есть огромная база данных со строками, структурированными по полям «дата, реклама, сайт, показы, клики»

Я получил их все через python, используя:

cursor.execute(select * from dabase)
data = cursor.fetchall()

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

row (1):(t1, ad1, site1) -> клики = 1 (t время)

row (2): (t2, ad1, site1) -> клики = 0

Таким образом, ad1 иУ site1 в точке t1 было нажатие> 0, и поэтому все точки в данных, содержащих ad1 и site1, должны быть взяты и помещены в другой список , который я назвал final_list, который будет содержать row (1) и row (2) (row (2) имеет 0 кликов, но с тех пор, как t1 ad1 и site1 имели клики> 0, поэтому эту строку также нужно брать)

Когда я пытался сделать это через MySQL Workbench, это заняло так много времени, что яполучено сообщение об ошибке «Потеряно соединение с базой данных».Я думаю, это происходит потому, что в таблице почти 40 миллионов строк, хотя мне кажется, что люди, работающие здесь с гораздо большими объемами данных, MySQL не в состоянии справиться с этим, поэтому я использовал python (фактически, чтобы получитьстроки с щелчками> 0 в Python заняли несколько секунд, в то время как через MySQL это заняло более 10 минут, я точно не знаю, как долго это происходило)

Затем я сначала выбрал точки объявления.и сайт с кликами> 0:

points = [(row[1], row[2]) for row in data if row[4]]
points = list(set(points))
dic = {}
for element in points:
    dic[element] = 1

Этот код занял всего несколько секунд.Имея словарь с требуемыми точками, я начал вставлять данные в final_list:

final_list = []
for row in data:
    try:
        if dic[(row[1], row[2])] == 1: final_list.append(row)
    except: continue

Но это занимает слишком много времени, и я пытаюсь найти способ заставить его работать быстрее.Возможно ли это?

Я ценю любую помощь!

Ответы [ 2 ]

2 голосов
/ 29 марта 2012

Я знаю, что в комментариях спрашивается, почему вы не можете просто сделать это в базе данных, что мне тоже интересно ... но что касается хотя бы адресации вашего кода, вам, вероятно, не понадобится несколько шаговв середине, такие как преобразование в список -> установить -> список -> словарь.Я уверен, что список append () убивает вас, а также циклы for.

Как насчет этого?

points = set((row[1], row[2]) for row in data if row[4])
final_list = [d for d in data if (d[1], d[2]) in points]

Вы даже можете увидеть, быстрее ли этополучите свою точку зрения:

from operator import itemgetter
from itertools import ifilter

points = set(ifilter(itemgetter(4), data))
getter = itemgetter(1,2)
final_list = [d for d in data if getter(d) in points]

Мой ответ дает ваш вопрос преимущество того, что у вас нет возможности делать это регулярно из SQL с лучшим SQL-запросом

0 голосов
/ 29 марта 2012

Вы заново изобретаете колесо.

Используйте предложение WHERE в запросе SELECT для фильтрации результатов вашего запроса.

cursor.execute("SELECT * FROM dabase WHERE clicks > 0")

Это быстрее, потому что:

  • База данных сильно оптимизирована, чтобы сделать SELECT ... WHERE очень быстрым. Это будет намного, намного быстрее, чем буквально любой метод, который вы используете для репликации предложения WHERE в Python.
  • Меньше данных нужно перемещать между сервером SQL и вами (важно, если ваш сервер SQL находится в сети.) Вместо того, чтобы сервер SQL отправлял вам все данные, большинство из которых вы ' Я хочу, чтобы SQL-сервер отправил вам отфильтрованные данные, которые вам действительно нужны.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...