Чтобы уточнить мой комментарий, что-то вроде этого.
Я предвижу, что у вас будет плохое время, пытаясь разместить 100 миллионов строк x 30 столбцов в 2 гигабайтах памяти.
df = None
for offset in itertools.count(step=chunksize):
print("Reading chunk %d..." % offset)
query = "select * from db.db_table order by id limit %d offset %d" % (chunksize, offset)
chunk_df = pd.read_sql(query, dbConnection)
if not chunk_df: # TODO: this check might not be correct
# No data in new chunk, so we probably have it all
break
if not df:
df = chunk_df
else:
df = pd.concat([df, chunk_df], copy=False)
# do things with DF