>

postgresql 데이터베이스에서 :

class Persons(models.Model):
    person_name = models.CharField(max_length=10, unique=True)

persons.csv  파일에 백만 개의 이름이 포함되어 있습니다.

$cat persons.csv
Name-1
Name-2
...
Name-1000000

다음을 원합니다 :

<올>
  • 존재하지 않는 이름 만들기
  • 데이터베이스를 쿼리하고 csv 파일에 포함 된 각 이름의 ID를 가져옵니다.
  • 내 접근 방식 :

    <올>
  • COPY 사용 명령 또는 django-postgres-copy 그것을 구현하는 응용 프로그램.

    또한 새로운 Postgresql-9.5 + 업데이트 기능 .

  • 이제 csv 파일의 모든 이름도 데이터베이스에 있습니다.

    데이터베이스에서 효율적인 방법으로 다른 CSV 파일로 ID를 가져와야합니다.

    • Q 사용 개체

      list_of_million_q = <iterate csv and append Qs>
      million_names = Names.objects.filter(list_of_million_q)
      
      

      또는

    • __in 이름 목록을 기준으로 필터링 :

      list_of_million_names = <iterate csv and append strings>
      million_names = Names.objects.filter(
          person_name__in=[list_of_million_names]
      )
      
      

      또는

      ?

  • ID를 가져 오는 위의 방법 중 어느 것이 효율적이라고 생각하지 않습니다.

    업데이트

    세 번째 옵션은 이 게시물 을 따라 위의 모든 것을 결합한 훌륭한 솔루션이어야합니다. .


    • 답변 # 1

      같은 것 :

      SELECT * FROM persons;
      
      

      이름 만들기 : 데이터베이스에서받은 이름 중 id 사전 :

      db_dict = {'Harry': 1, 'Bob': 2, ...}
      
      

      사전 쿼리 :

      ids = []
      for name in list_of_million_names:
          if name in db_dict:
              ids.append(db_dict[name])
      
      

      이 방법으로 느린 if x in list 와 달리 빠른 사전 인덱싱을 사용합니다.  접근.

      그러나 실제로 확실하게 알 수있는 유일한 방법은이 3 가지 접근법을 벤치마킹하는 것입니다.

    • 답변 # 2

      이 게시물은 RETURNING 사용법에 대해 설명합니다   ON CONFLICT 와 함께  따라서 데이터베이스에 csv 파일의 내용을 삽입하는 동안 삽입이 성공하거나 고유 제한 조건으로 인해 삽입이 생략되면 id가 다른 테이블에 저장됩니다.

      나는 sqlfiddle에서 그것을 테스트했는데 COPY 에 사용 된 것과 유사한 설정을 사용했습니다.  고유 제한 조건을 고려하여 csv 파일에서 직접 데이터베이스에 삽입하는 명령입니다.

      스키마 :

      CREATE TABLE IF NOT EXISTS label (
        id serial PRIMARY KEY,
        label_name varchar(200) NOT NULL UNIQUE
        );
      INSERT INTO label (label_name) VALUES
        ('Name-1'),
        ('Name-2');
      CREATE TABLE IF NOT EXISTS ids (
        id serial PRIMARY KEY,
        label_ids varchar(12) NOT NULL
        );
      
      

      스크립트 :

      CREATE TEMP TABLE tmp_table
      (LIKE label INCLUDING DEFAULTS)
      ON COMMIT DROP;
      INSERT INTO tmp_table (label_name) VALUES
        ('Name-2'),
        ('Name-3');
      WITH ins AS(
        INSERT INTO label 
        SELECT *
        FROM tmp_table
        ON CONFLICT (label_name) DO NOTHING
        RETURNING id
      )
      INSERT INTO ids (label_ids)
      SELECT
        id FROM ins
      UNION ALL
      SELECT
        l.id FROM tmp_table
      JOIN label l USING(label_name);
      
      

      출력 :

      SELECT * FROM ids;
      SELECT * FROM label;
      
      

  • 이전 android - Duktape를 구성하는 방법?
  • 다음 xmlhttprequest - Laravel Guzzle 구문 분석 오류 양식 JSON 형식