J'essaie d'analyser les valeurs d'un fichier CSV vers une base de données SQLite, mais le fichier est assez volumineux (~ 2 500 000 lignes). J'ai couru mon programme pendant quelques heures, imprimant où il était, mais selon mes calculs, le fichier aurait pris environ 100 heures à analyser complètement, donc je l'ai arrêté.Ajout efficace d'énormes quantités de données à partir de fichiers CSV dans une base de données SQLite en Java
Je vais devoir exécuter ce programme en tant que processus d'arrière-plan au moins une fois par semaine, sur un nouveau fichier CSV qui est environ 90% similaire au précédent. J'ai trouvé quelques solutions pour améliorer mon programme. Cependant, je ne sais pas grand-chose sur les bases de données, alors j'ai des questions sur chacune de mes solutions.
Existe-t-il un moyen plus efficace de lire un fichier CSV que ce que j'ai déjà?
Instanciation d'un objet ObjectOutputStream, et stockage en tant que BLOB de façon coûteuse? Je pourrais directement ajouter les valeurs à la place, mais j'utilise le BLOB plus tard, le stocker maintenant m'évite d'en instancier un nouveau plusieurs fois.
Le regroupement de connexions ou la modification de la manière dont j'utilise la connexion d'une autre manière sont-ils plus efficaces? Je définis la colonne URL comme UNIQUE afin que je puisse utiliser INSERT OR IGNORE, mais le test sur des jeux de données plus petits (~ 10000 lignes) indique qu'il n'y a pas de gain de performances par rapport à la suppression de la table et au repeuplement. Existe-t-il un moyen plus rapide d'ajouter uniquement des valeurs uniques?
Y a-t-il des erreurs évidentes que je commets? (Encore une fois, je sais très peu de choses sur les bases de données)
public class Database{ public void createResultsTable(){ Statement stmt; String sql = "CREATE TABLE results(" + "ID INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, " + "TITLE TEXT NOT NULL, " + "URL TEXT NOT NULL UNIQUE, " ... ... + "SELLER TEXT NOT NULL, " + "BEAN BLOB);"; try { stmt = c.createStatement(); stmt.executeUpdate(sql); } catch (SQLException e) { e.printStackTrace();} } public void addCSVToDatabase(Connection conn, String src){ BufferedReader reader = null; DBEntryBean b; String[] vals; try{ reader = new BufferedReader(new InputStreamReader(new FileInputStream(src), "UTF-8")); for(String line; (line = reader.readLine()) != null;){ //Each line takes the form: "title|URL|...|...|SELLER" vals = line.split("|"); b = new DBEntryBean(); b.setTitle(vals[0]); b.setURL(vals[1]); ... ... b.setSeller(vals[n]); insert(conn, b); } } catch(){ } } public void insert(Connection conn, DBEntryBean b){ PreparedStatement pstmt = null; String sql = "INSERT OR IGNORE INTO results(" + "TITLE, " + "URL, " ... ... + "SELLER, " + "BEAN" + ");"; try { pstmt = c.prepareStatement(sql); pstmt.setString(Constants.DB_COL_TITLE, b.getTitle()); pstmt.setString(Constants.DB_COL_URL, b.getURL()); ... ... pstmt.setString(Constants.DB_COL_SELLER, b.getSeller()); // ByteArrayOutputStream baos = new ByteArrayOutputStream(); // oos = new ObjectOutputStream(baos); // oos.writeObject(b); // byte[] bytes = baos.toByteArray(); // pstmt.setBytes(Constants.DB_COL_BEAN, bytes); pstmt.executeUpdate(); } catch (SQLException e) { e.printStackTrace(); } finally{ if(pstmt != null){ try{ pstmt.close(); } catch (SQLException e) { e.printStackTrace(); } } } } }
Idéalement, vous ne voulez pas créer une nouvelle instruction préparée avec chaque ligne du fichier. Vous voulez le réutiliser. – 4castle
Il semble que votre code fonctionne actuellement, et vous cherchez à l'améliorer. Généralement, ces questions sont trop controversées pour ce site, mais vous pourriez trouver plus de chance à [CodeReview.SE] (// codereview.stackexchange.com/tour). N'oubliez pas de lire [leurs exigences] (// codereview.stackexchange.com/help/on-topic) car ils sont un peu plus strictes que ce site. – 4castle
@ 4castle Merci. J'ai déplacé le PreparedStatement hors de la boucle, et l'ai testé sur 1000 lignes et gagné environ 3 secondes d'amélioration. Donc c'est un début. – Sam