Welcome! ๐Ÿ™‹โ€โ™‚๏ธ View more

Engineering ๐Ÿ’ป/CS

[PostgreSQL] Python์—์„œ ๋‹ค์ค‘ ํ–‰์„ Insertํ•˜๋Š” ๋‹ค์–‘ํ•œ ๋ฐฉ๋ฒ•๊ณผ ๋น„๊ต

DeepFlame 2022. 2. 10. 19:00

๐Ÿค” Python์œผ๋กœ DB์— ๋ฐ์ดํ„ฐ๋ฅผ ์ž…๋ ฅํ•  ๋•Œ, ๋‹ค์ค‘ ํ–‰์„ ์ž…๋ ฅํ•˜๋Š” ๊ฒฝ์šฐ๊ฐ€ ๋งŽ์„ ๊ฒƒ์ด๋‹ค. ์ด๋ฅผ ์–ด๋–ป๊ฒŒ ์‹คํ–‰ํ•ด์•ผ ๊ฐ€์žฅ ๋น ๋ฅด๊ฒŒ ์ž…๋ ฅํ•  ์ˆ˜ ์žˆ์„๊นŒ?

๐Ÿ˜€ ์ด๋Ÿฌํ•œ ๊ณ ๋ฏผ์— 3๊ฐ€์ง€ ๋ฐฉ๋ฒ•์„ ์‹คํ–‰ํ•ด๋ดค๊ณ , ๊ฐ ๋ฐฉ๋ฒ•์ด ์‹œ๊ฐ„์ด ์–ด๋–ป๊ฒŒ ์ฐจ์ด๋‚˜๋Š” ์ง€ ๊ณต์œ ํ•ด๋ณด๊ณ ์ž ํ•œ๋‹ค.

 

๋จผ์ € ์ž…๋ ฅํ•  ๋ฐ์ดํ„ฐ์™€ DB๋ฅผ ์—ฐ๊ฒฐํ•˜์ž.

  1. ์‚ฌ์šฉ๋  ๋ฐ์ดํ„ฐ๋Š” 10๋งŒ๊ฐœ์˜ ํ–‰๊ณผ 3๊ฐœ์˜ ์—ด์„ ๊ฐ€์ง„ Integer ๋ฐ์ดํ„ฐ๋ฅผ ์‚ฌ์šฉํ•  ๊ฒƒ์ด๋‹ค. 
  2. DB๋Š” PostgreSQL๋กœ ๊ตฌ์ถ•ํ•œ DB๋ฅผ ํ™œ์šฉํ•  ๊ฒƒ์ด๋‹ค.
import time
import psycopg2

N = 100000
data = [(i,i,i) for i in range(N)]
print('data length: ', len(data)) #10๋งŒ๊ฐœ์˜ ํ–‰

db = psycopg2.connect(host='localhost', dbname='test', user='postgres', password='postgres', port=5432)
cursor = db.cursor()

 

 

1. ๋ฐ˜๋ณต๋ฌธ ํ™œ์šฉ


sql = "INSERT INTO public.inserttest VALUES (%s,%s,%s);"

start_time = time.time()
for row in data:
    try:
        cursor.execute(sql, row)
    except Exception as e:
        print("Insert Error: ", e)

db.commit()
print("%s: %.5f secs" % ("Taken Time", time.time() - start_time))

for๋ฌธ์„ ํ™œ์šฉํ•œ ๋ฐฉ๋ฒ•์ด๋‹ค. ์‹œ๊ฐ„์€ ๋ชจ๋‘ ์ž…๋ ฅํ•˜๋Š”๋ฐ, ์•ฝ 6.59์ดˆ ๊ฑธ๋ฆฐ๋‹ค.

์ด๋ฅผ SQL ๋ฌธ์œผ๋กœ ํ’€์–ด์“ฐ์ž๋ฉด ์•„๋ž˜์™€ ๊ฐ™๋‹ค.

INSERT INTO public.inserttest VALUES (0,0,0)
INSERT INTO public.inserttest VALUES (1,1,1)
INSERT INTO public.inserttest VALUES (2,2,2)
INSERT INTO public.inserttest VALUES (3,3,3)
INSERT INTO public.inserttest VALUES (4,4,4);

 

 

2. Executemany ํ•จ์ˆ˜ ํ™œ์šฉ


sql = "INSERT INTO public.inserttest VALUES (%s,%s,%s);"

start_time = time.time()
try:
    cursor.executemany(sql, data)
except Exception as e:
    print("Insert Error: ", e)

db.commit()
print("%s: %.5f secs" % ("Taken Time", time.time() - start_time))

๋ฐ˜๋ณต๋ฌธ์„ ์ œ๊ฑฐํ•˜๊ณ , executemany ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•ด์„œ ์ข€ ๋” ์ฝ”๋“œ ๊ฐ€๋…์„ฑ์ด ์˜ฌ๋ผ๊ฐ„ ๋ชจ์Šต๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ์†Œ๋ชจ๋˜๋Š” ์‹œ๊ฐ„์€ ์œ ์˜๋ฏธํ•˜๊ฒŒ ๋‹ค๋ฅด์ง„ ์•Š์€ ๊ฒƒ์œผ๋กœ ๋ณด์ธ๋‹ค. 

 

๐Ÿค” ํ•˜์ง€๋งŒ ์•„๋ž˜ ๋ธ”๋กœ๊ทธ๋ฅผ ํ™•์ธํ•ด๋ณด๋ฉด ์œ ์˜๋ฏธํ•˜๊ฒŒ ์‹œ๊ฐ„์ด ๋‹จ์ถ•๋œ ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋Š”๋ฐ, ํ•„์ž์˜ ๊ฒฝ์šฐ๋Š” ๊ทธ๋ ‡์ง€ ์•Š์•˜๋‹ค. ๋‚˜์ค‘์— ์ข€ ๋” ์‚ดํŽด๋ณด์•„์•ผํ•  ๋ฌธ์ œ์ด๋‹ค.

https://blog.actorsfit.com/a?ID=01750-ec0f0ded-771d-4b06-a47f-7adb203e72c2 

 

 

3. mogrify ํ•จ์ˆ˜ ์‚ฌ์šฉ


args_str = ", ".join([cursor.mogrify('(%s,%s,%s)', row).decode('utf-8') for row in data])
sql = "INSERT INTO public.inserttest VALUES {data};".format(data=args_str)

start_time = time.time()
try:
    cursor.execute(sql)
except Exception as e:
    print("Insert Error: ", e)

db.commit()
print("%s: %.5f secs" % ("Taken Time", time.time() - start_time))

๐Ÿ”ฅ ์‹œ๊ฐ„์ด ๋‹ค์ด๋‚˜๋ฏนํ•˜๊ฒŒ ์ค„์—ˆ๋‹ค! 100,000 ๊ฐœ์˜ ํ–‰ ๊ธฐ์ค€์œผ๋กœ 10๋ฐฐ ๊ฐ€๊นŒ์ด ์‹œ๊ฐ„์ด ์ ˆ์•ฝ๋œ ์…ˆ์ด๋‹ค.

๐Ÿค” ์™œ ๊ทธ๋Ÿด๊นŒ? ๊ทธ ์ด์œ ๊ฐ€ ๋ช…์‹œ๋˜์–ด ์žˆ๋Š” ๋ฌธ์„œ๋Š” ์—†์ง€๋งŒ, ์ถ”์ธกํ•ด๋ณด์ž๋ฉด 3๋ฒˆ ๋ฐฉ๋ฒ•์—์„œ๋Š” INSERT๋ฌธ ํ•œ ๋ฒˆ์— ๋ชจ๋“  ๋ฐ์ดํ„ฐ๊ฐ€ ์ž…๋ ฅ๋˜์–ด ํŠธ๋žœ์žญ์…˜ ํšŸ์ˆ˜๊ฐ€ ์œ ์˜๋ฏธํ•˜๊ฒŒ ์ค„์–ด๋“ ๋‹ค. ์ด๊ฒƒ์ด ์‹œ๊ฐ„์ด ์ค„์–ด๋“  ์ด์œ ๊ฐ€ ์•„๋‹Œ๊ฐ€ ์ถ”์ธก๋œ๋‹ค.

INSERT INTO public.inserttest VALUES 
		(0,0,0), (1,1,1), (2,2,2), (3,3,3), (4,4,4);

 

 

๊ฒฐ๋ก 


Insert ๋ฌธ์—์„œ๋Š” mogrify ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ๊ฐ€์žฅ ์†๋„๊ฐ€ ๋น ๋ฅด๋‹ค!

  ๋ฐ˜๋ณต๋ฌธ ์‚ฌ์šฉ Executemany ์‚ฌ์šฉ mogrify ์‚ฌ์šฉ
์†Œ์š” ์‹œ๊ฐ„ 6.592 ์ดˆ 5.925 ์ดˆ 0.652 ์ดˆ