Avatar billede jesperwerge Nybegynder
09. november 2009 - 15:11 Der er 11 kommentarer og
1 løsning

hurtigst måde at insætte store mængder data i MS SQL 2005

Hej

Jeg har kodet et lille program til at konvertere fast felt  positionerede tekst filer til MSSQL Database. Koden virker fint og uden fejl.

Men :) - jeg vil gerne optimere de steder i programmet hvor det taget længst tid, hvilket er at loade data ind i databasen
136 MB tekst filer tager omkring 50 minutter at indlæse og giver en MDB file på ca. 20 MB.

Jeg bruger java jvm 1.5_20 og Microsoft egen JDBC (sqljdbc_1.1.1501.101_enu)

Lige nu kalder jeg et statement pr. insert linje, men overvejer at benytte batch funktion til at indsætte alle rækker i en tabel på samme tid, men ved ikke om det vil sætte mere fart på eller om eksekveringen vil være det samme!

jeg håber nogle af jer vil give jeres mening og eventuelle forslag til optimeringer.
Avatar billede arne_v Ekspert
09. november 2009 - 15:19 #1
1) genbrug af prepared statement
2) bundte 1000 inserts per transaction (commit)

vil give en hel del.

Brug af batch giver muligvis yderligere en del, men det har jeg ikke erfaring med.
Avatar billede arne_v Ekspert
09. november 2009 - 15:21 #2
Derudover skal du sikre dig at du laeser tekst filen med en paen stor buffer stoerrelse.
Avatar billede jesperwerge Nybegynder
09. november 2009 - 20:38 #3
Hej arne_v,

Tak for dine kommentarer.

Jeg læser en fil ind af gangen og bruger en bufferedreader for at læse hver linje som herefter skal give en insert, oftes er der mellem 7500 og 10000 linjer i en fil.

Synes ikke jeg kan finde en måde at sætte buffer size på min BufferedReader - har du en anden måde at indlæse en file på, hvor jeg stadig kan arbejde udfra 1 linje af gangen?

/Jesper
Avatar billede arne_v Ekspert
09. november 2009 - 21:02 #4
BufferedReader FileReader kan ikke, men BufferedReader InputStreamReader BufferedInputStream FileINputStream boer kunne.

Jeg ved dog ikke om det vil give noget.
Avatar billede arne_v Ekspert
09. november 2009 - 21:03 #5
Jeg ved dog ikke om det vil give noget i forhold til BufferedReaders default buffer.
Avatar billede arne_v Ekspert
09. november 2009 - 21:03 #6
Du kunne ogsaa proeve at indsaette multithreaded for at undgaa venten paa IO.
Avatar billede jesperwerge Nybegynder
10. november 2009 - 07:33 #7
Hej

Lige nu indlæser jeg en fil afgangen, har maks 27 filer i alt, som hver kan have minimum 7500 linjer i hver og i mange af filerne vil der være x antal af 7500 linjer, ganske store datagrundlag.

overvejer at sætte flere insert igang på flere filer, men det er vel det du mener med miltithreaded?

er der noget man skal være opmærksom på i forbindelse med multitreaded struktur, og hvordan ville man gribe det an?

/Jesper
Avatar billede jesperwerge Nybegynder
10. november 2009 - 16:42 #8
Hej

jeg forsøger mig med at ændre min dynamiske opbygning af mit prepared statement, hvilket går ok - min kode ser således ud:

String SQLstatement;
            PreparedStatement stmt = null;
            String columns = "INSERT INTO  " + t.get_tableName() + " (";
            String values = " VALUES (";
            int lastField = t.get_fields().size();
            int i= 0;
            //building the prepared statement SQL
            for(Field f : t.get_fields())
            {
                if((i+1) == lastField)
                {
                    columns += f.get_fieldName()+ "";
                    values += "?";
                }
                else
                {
                    columns += f.get_fieldName()+ ", ";
                    values += "?, ";
                }
                i++;
            }
            columns += ")";
            values += ")";
            SQLstatement = columns + " " + values;
            debug("Config table INSERT INTO " + t.get_tableName() + " With SQL " + SQLstatement);
            try
            {
                stmt = _con.prepareStatement(SQLstatement);
            }
            catch (SQLException e)
            {
                fatal("ERROR prepare statement: ", e);
            }

Når jeg derimod vil opbygge alle mine set<Type> på det prepared statement går det ofte galt med en fejl om at paramenter number 2 does not have any value...hvilket ikke er tilfældet.

Min kode for at opbygge set<Type> ser således ud:

while ((line = br.readLine()) != null)
            {   
                int d= 1;
                for (Iterator<Field> iterator = t.get_fields().iterator(); iterator.hasNext();)
                {
                    Field f = iterator.next();
                   
                    int endIndex = (f.get_fieldStartPos() + f.get_fieldLength());
                    String value = "";
                    value = line.substring(f.get_fieldStartPos(), endIndex).trim();
                    debug("Value of this fieldnr" + "(" + d + "): " + value + " lenght: " + value.length());
                    if(value.length() == 0)
                    {
                        try
                        {
                            stmt.setString(d, "");
                        }
                        catch(SQLException e)
                        {
                            fatal("ERROR adding prepared statement to batch ",e);
                        }
                    }
                    else
                    {
                        try
                        {
                            stmt.setString(d, value);
                        }
                        catch(SQLException e)
                        {
                            fatal("ERROR adding prepared statement to batch ",e);
                        }
                    }
                    try
                    {
                        stmt.addBatch();
                    }
                    catch (SQLException e)
                    {
                        fatal("ERROR adding the statement ",e);
                    }
                    d++;
                }

fejlen om at den 2. parameter ikke er udfyldt er ikke korrekt, den er udfyld når jeg kigger på felt indhold.

har du nogen ide til hvorfor eller hvor jeg skal kigge hen?
Avatar billede jesperwerge Nybegynder
10. november 2009 - 18:40 #9
dette er den mere konkrete fejl jeg får:

INSERT INTO  BAAD (BA_number, Address_type, Address_Line_1, Address_Line_2, Country_code, Electronic_address_1, Electronic_address_2)  VALUES (?, ?, ?, ?, ?, ?, ?)
Value of this fieldnr(1): 303000627 lenght: 9
Value of this fieldnr(2): Q lenght: 1
Value of this fieldnr(3): OEA-TEST 1 A 1 lenght: 14
Value of this fieldnr(4): 02600 ESPOO lenght: 11
Value of this fieldnr(5): FIN lenght: 3
Value of this fieldnr(6):  lenght: 0
Value of this fieldnr(7):  lenght: 0
ERROR executing Batch to Database:
java.sql.BatchUpdateException: com.microsoft.sqlserver.jdbc.SQLServerException: The value is not set for the parameter number 2.

de to felter 6 og 7 får en "" som værdi. har prøvet med SetNull også uden held.

/Werge
Avatar billede jesperwerge Nybegynder
10. november 2009 - 18:41 #10
men forstår ikke at den brokker sig over parameter 2!
Avatar billede jesperwerge Nybegynder
20. februar 2010 - 12:26 #11
Hej Arne,

jeg har glemt at give dig points - undskyld, vil du smide et svar, tak

/Jesper
Avatar billede arne_v Ekspert
20. februar 2010 - 15:28 #12
OK

du fik løst det sidste problem?
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester