1
0
mirror of https://github.com/ilri/dspace-statistics-api.git synced 2025-05-10 07:06:01 +02:00

Compare commits

...

8 Commits

Author SHA1 Message Date
7499b89d99 CHANGELOG.md: Move unreleased changes to v0.4.1 2018-09-27 08:15:54 +03:00
2c1e4952b1 indexer.py: Remove comment
I had left this there so I could remember how to get the number of
facets, but I don't need it anymore.
2018-09-26 23:27:48 +03:00
379f202c3f CHANGELOG.md: Add unreleased changes 2018-09-26 23:26:48 +03:00
560fa6056d README.md: Remove batch inserts from TODO 2018-09-26 23:25:35 +03:00
385a34e5d0 indexer.py: Use psycopg2's execute_values to batch inserts
Batch inserts are much faster than a series of individual inserts
because they drastically reduce the overhead caused by round-trip
communication with the server. My tests in development confirm:

  - cursor.execute(): 19 seconds
  - execute_values(): 14 seconds

I'm currently only working with 4,500 rows, but I will experiment
with larger data sets, as well as larger batches. For example, on
the PostgreSQL mailing list a user reports doing 10,000 rows with
a page size of 100.

See: http://initd.org/psycopg/docs/extras.html#psycopg2.extras.execute_values
See: https://github.com/psycopg/psycopg2/issues/491#issuecomment-276551038
2018-09-26 23:10:29 +03:00
d0ea62d2bd database.py: Use one line for psycopg2 imports 2018-09-26 22:23:24 +03:00
366ae25b8e README.md: Add link to psycopg2 issue about batch inserts 2018-09-26 22:23:08 +03:00
0f3054ae03 README.md: Add TODO about batch DB inserts 2018-09-26 16:31:13 +03:00
3 changed files with 26 additions and 11 deletions

View File

@ -4,6 +4,10 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [0.4.1] - 2018-09-26
### Changed
- Use execute_values() to batch insert records to PostgreSQL
## [0.4.0] - 2018-09-25
### Fixed
- Invalid OnCalendar syntax in dspace-statistics-indexer.timer

View File

@ -2,8 +2,7 @@ from config import DATABASE_NAME
from config import DATABASE_USER
from config import DATABASE_PASS
from config import DATABASE_HOST
import psycopg2
import psycopg2.extras
import psycopg2, psycopg2.extras
def database_connection():
connection = psycopg2.connect("dbname={} user={} password={} host='{}'".format(DATABASE_NAME, DATABASE_USER, DATABASE_PASS, DATABASE_HOST), cursor_factory=psycopg2.extras.DictCursor)

View File

@ -32,6 +32,7 @@
from database import database_connection
import json
import psycopg2.extras
from solr import solr_connection
def index_views():
@ -64,6 +65,9 @@ def index_views():
cursor = db.cursor()
# create an empty list to store values for batch insertion
data = []
while results_current_page <= results_num_pages:
print('Indexing item views (page {} of {})'.format(results_current_page, results_num_pages))
@ -77,19 +81,20 @@ def index_views():
'facet.offset':results_current_page * results_per_page
}, rows=0)
# check number of facets returned in the last query
#results_currentNumFacets = len(res.get_facets()['id'])
# SolrClient's get_facets() returns a dict of dicts
views = res.get_facets()
# in this case iterate over the 'id' dict and get the item ids and views
for item_id, item_views in views['id'].items():
cursor.execute('''INSERT INTO items(id, views) VALUES(%s, %s)
ON CONFLICT(id) DO UPDATE SET downloads=excluded.views''',
(item_id, item_views))
data.append((item_id, item_views))
# do a batch insert of values from the current "page" of results
sql = 'INSERT INTO items(id, views) VALUES %s ON CONFLICT(id) DO UPDATE SET downloads=excluded.views'
psycopg2.extras.execute_values(cursor, sql, data, template='(%s, %s)')
db.commit()
# clear all items from the list so we can populate it with the next batch
data.clear()
results_current_page += 1
cursor.close()
@ -119,6 +124,9 @@ def index_downloads():
cursor = db.cursor()
# create an empty list to store values for batch insertion
data = []
while results_current_page <= results_num_pages:
print('Indexing item downloads (page {} of {})'.format(results_current_page, results_num_pages))
@ -136,12 +144,16 @@ def index_downloads():
downloads = res.get_facets()
# in this case iterate over the 'owningItem' dict and get the item ids and downloads
for item_id, item_downloads in downloads['owningItem'].items():
cursor.execute('''INSERT INTO items(id, downloads) VALUES(%s, %s)
ON CONFLICT(id) DO UPDATE SET downloads=excluded.downloads''',
(item_id, item_downloads))
data.append((item_id, item_downloads))
# do a batch insert of values from the current "page" of results
sql = 'INSERT INTO items(id, downloads) VALUES %s ON CONFLICT(id) DO UPDATE SET downloads=excluded.downloads'
psycopg2.extras.execute_values(cursor, sql, data, template='(%s, %s)')
db.commit()
# clear all items from the list so we can populate it with the next batch
data.clear()
results_current_page += 1
cursor.close()