Что такое быстрая проверка того, какие идентификаторы существуют в таблице postgreSQL
Я написал следующую функцию, но она работает очень медленно, когда len(x)
больше 500 000
import psycopg2
conn = psycopg2.connect(...)
cursor = conn.cursor(cursor_factory=psycopg2.extras.DictCursor)
def check_exist(lst):
exist = []
not_exist = []
for i in lst:
cursor.execute(f"SELECT * FROM table1 where id = {i}")
row = cursor.fetchone()
if row:
exist.append(i)
else:
not_exist.append(i)
return exist, not_exist
x, y = check_exist(['2','4','3000','50000','10000000'])
В любом случае, да, вы делаете 500 000 SELECT *
запросов для 500 000 идентификаторов. Это будет медленно. Это почти наверняка проблема XY. Если вы объясните, чего вы пытаетесь достичь, мы, вероятно, сможем порекомендовать лучший подход.
@Chris Я пишу скрипт, который должен создать 2 таблицы на основе пользовательского ввода, пользовательский ввод в моей модели даст мне список идентификаторов (в идеале пользователь выберет максимум 10000 идентификаторов), но я хочу сделать это быстрее, поэтому я ищу лучшие способы сделать это
«пользовательский ввод в моей модели даст мне список идентификаторов» — почему? Что вы хотите делать с этими идентификаторами?
@Chris Возможно, мне следовало упомянуть, что это для приложения Django, где пользователь отправляет форму (выбирает элементы), при отправке создается список идентификаторов, идентификаторы необходимо проверить, если они существуют в таблице -> если да, то товар есть в наличии, иначе его нет в наличии, наконец, товары, выбранные пользователем, будут отображаться на 2 разных веб-страницах.
...У меня так много вопросов по этому поводу. Откуда в первую очередь берутся идентификаторы? Пользователи вводят числа? Поиск вещей? Зачем кому-то отправлять от 10 до 500 тысяч элементов в одной форме? Почему «в наличии» означает «идентификатор существует»? Разве наличие удостоверения личности и наличие на складе не должны быть разными вещами? У вас определенно, определенно проблема XY, как я уже говорил ранее. Пожалуйста, уменьшите масштаб и переосмыслите то, чего вы пытаетесь достичь. Если вы объясните, что мы могли бы помочь, но это также может быть слишком широким для SO.
Вы можете использовать предложение IN. Создайте список с вашими идентификаторами. Повторите список в своем приложении, чтобы проверить, какие идентификаторы не фигурируют в списке найденных записей.
Выберите идентификатор из таблицы 1, где идентификатор IN ([ваш список])
Суть: запрос меньшего количества полей из таблицы делает ваш запрос более эффективным.
Предложение IN
с 500 000 записей, вероятно, тоже не лучшая идея. У OP проблема XY, и нам нужно больше узнать о том, что они пытаются сделать, прежде чем мы сможем дать хороший совет.
Мне все равно, что находится в строке в данный момент, я просто проверяю, существует ли идентификатор или нет. Я буду использовать идентификатор в более поздней функции
Вы можете использовать ANY и позволить Postgres сделать большую часть работы:
import psycopg2, time
# database is in a datacenter just using a tunnel!
conn = psycopg2.connect("dbname=mf port=5959 host=localhost user=mf_usr")
cur = conn.cursor()
ids = [x for x in range(0, 750000)]
sql = """
SELECT array_agg(id) from __users where id = ANY(%s);
"""
# array_agg: Postgres returns an array of ids!
_start = time.time()
cur.execute(sql, (ids, ))
existingIds = cur.fetchone()[0]
missingIds = set(ids) - set(existingIds)
print(len(existingIds))
print(len(missingIds))
print('Took: %.6f seconds' % (time.time() - _start))
Вне:
284365
465635
Took: 5.564851 seconds
Примечание. Убедитесь, что у столбца идентификатора есть индекс.
именно то, что я просил, кстати, вы можете использовать ids = list(range(750000))
Я все еще думаю, что это была проблема XY, но я думаю, вы ответили на вопрос ОП.
@goku: я всегда забываю об этом :)
Почему вы вообще проверяете, существует ли идентификатор в базе данных из Python?