Visual Basic, .NET, ASP, VBScript
 

   
   
     

Форум - Работа с данными

Страница: 1 |

 

  Вопрос: Пишу 30000 строк в базу Access, как ускорить? Добавлено: 04.11.05 23:35  

Автор вопроса:  Pantalone
Экспериментирую тут с заливкой большого объема данных в базу Access.
Данные заливаются в одну таблицу, которая не имеет ни ключей ни индексов.
Берутся данные из заполненного массива.
Пробовал следующие способы в порядке возрастания времени работы:

1) - 192 секунды
rst.Open strsql, cnnData, adOpenStatic, adLockBatchOptimistic
.AddNew
rst.UpdateBatch

2) - 228 секунд
rst.Open strsql, cnnData, adOpenKeyset, adLockOptimistic
.AddNew
.Update

3) - 248 секунд
cnnData.Execute strsql, , adCmdText + adExecuteNoRecords

4) - 254 секунды
cnnData.Execute strsql

Последние на равных почти, а кругом обещали что 3 быстрее 4. Ну да не в этом вопрос, как бы все это ускорить? И почему так долго, в то время когда импорт из текстового файла те же самые 30000 строк в ту же таблицу занимает пару-тройку секунд?

Ответить

  Ответы Всего ответов: 14  

Номер ответа: 1
Автор ответа:
 GSerg



Вопросов: 0
Ответов: 1876


 Профиль | | #1 Добавлено: 04.11.05 23:54
5) Хранимый INSERT-запрос в базе Access, вызов через ADODB.Command .Execute ,,adExecuteNoRecords

6) Linked table на текстовый файл с последующим INSERT INTO t1 SELECT * FROM t2.

Ответить

Номер ответа: 2
Автор ответа:
 Pantalone



Вопросов: 32
Ответов: 104
 Профиль | | #2 Добавлено: 04.11.05 23:59
С текстовым файлом некрасиво как-то.
Можно по 5 пункту немного подробнее?
Забыл сказать что работа в VB6

Ответить

Номер ответа: 3
Автор ответа:
 GSerg



Вопросов: 0
Ответов: 1876


 Профиль | | #3 Добавлено: 05.11.05 00:55
Понятно, что не в VC++ Builder'е...

30000 записей... А щас проверю, кстати...

Ответить

Номер ответа: 4
Автор ответа:
 EROS



Вопросов: 58
Ответов: 4255
 Профиль | | #4 Добавлено: 05.11.05 01:08
а с DAO не эксперементировал,может быстрее будет? Хотелось бы взглянуть на результаты теста.. что-то меня тоже заинтересовал этот вопрос.. ))

Ответить

Номер ответа: 5
Автор ответа:
 GSerg



Вопросов: 0
Ответов: 1876


 Профиль | | #5 Добавлено: 05.11.05 01:21
Да, с хранимым запросом быстрее всего, хотя с временным файлом не проверял, раз некрасиво...

Допустим, 12 столбцов в таблице, два числовых и 10 строковых (по порядку).
Открываем Access, создаём новый запрос, пишем:
PARAMETERS p1 Long, p2 Long, s1 Text ( 50 ), s2 Text ( 50 ), s3 Text ( 50 ), s4 Text ( 50 ), s5 Text ( 50 ), s6 Text ( 50 ), s7 Text ( 50 ), s8 Text ( 50 ), s9 Text ( 50 ), s10 Text ( 50 );
INSERT INTO Table1
VALUES (p1, p2, s1, s2, s3, s4, s5, s6, s7, s8, s9, s10);


Сохраняем под именем Query1.

Код:
  Dim conn As ADODB.Connection, i As Long, c As ADODB.Command
  Dim arr(1 To 10) As String
  
  'Эмуляция массива с данными
  For i = LBound(arr) To UBound(arr)
    arr(i) = String$(Rnd * 49 + 1, Rnd * 50 + 90)
  Next
  
  Set conn = New ADODB.Connection
  conn.IsolationLevel = adXactReadCommitted
  conn.Open "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=c:\db3.mdb;Mode=Read|Write|Share Deny None;Persist Security Info=False"
  
  Set c = New ADODB.Command
  Set c.ActiveConnection = conn
  c.CommandType = adCmdStoredProc
  c.CommandText = "Query1"
  c.Parameters.Append c.CreateParameter("p1", adInteger, adParamInput)
  c.Parameters.Append c.CreateParameter("p2", adInteger, adParamInput)
  c.Parameters.Append c.CreateParameter("s1", adVarWChar, adParamInput, 50)
  c.Parameters.Append c.CreateParameter("s2", adVarWChar, adParamInput, 50)
  c.Parameters.Append c.CreateParameter("s3", adVarWChar, adParamInput, 50)
  c.Parameters.Append c.CreateParameter("s4", adVarWChar, adParamInput, 50)
  c.Parameters.Append c.CreateParameter("s5", adVarWChar, adParamInput, 50)
  c.Parameters.Append c.CreateParameter("s6", adVarWChar, adParamInput, 50)
  c.Parameters.Append c.CreateParameter("s7", adVarWChar, adParamInput, 50)
  c.Parameters.Append c.CreateParameter("s8", adVarWChar, adParamInput, 50)
  c.Parameters.Append c.CreateParameter("s9", adVarWChar, adParamInput, 50)
  c.Parameters.Append c.CreateParameter("s10", adVarWChar, adParamInput, 50)
  c.Prepared = True
  
  Me.Print Now
  For i = 1 To 30000
    c.Parameters("p1";).Value = 12345
    c.Parameters("p2";).Value = 54321
    c.Parameters("s1";).Value = arr(1)
    c.Parameters("s2";).Value = arr(2)
    c.Parameters("s3";).Value = arr(3)
    c.Parameters("s4";).Value = arr(4)
    c.Parameters("s5";).Value = arr(5)
    c.Parameters("s6";).Value = arr(6)
    c.Parameters("s7";).Value = arr(7)
    c.Parameters("s8";).Value = arr(8)
    c.Parameters("s9";).Value = arr(9)
    c.Parameters("s10";).Value = arr(10)
    c.Execute , , adExecuteNoRecords
  Next
  Me.Print Now
  
  conn.Close

Ответить

Номер ответа: 6
Автор ответа:
 Pantalone



Вопросов: 32
Ответов: 104
 Профиль | | #6 Добавлено: 05.11.05 15:32
EROS
а с DAO не эксперементировал,может быстрее будет? Хотелось бы взглянуть на результаты теста.. что-то меня тоже заинтересовал этот вопрос.. ))

Проверил... Чуть со стула не упал.

DAO
5) - 144 секунды
MyDB.Execute strsql, dbFailOnError

6) - 20 (!!!!) секунд
Set rstElements = MyDB.OpenRecordset(strsql, 2)
.AddNew
.Update

Мда... Говорят с если прога работает на DAO то часто бывают проблемы с установкой ее на другие компы, потому и не хотел с DAO связываться. Теперь сижу репу чешу.

Ответить

Номер ответа: 7
Автор ответа:
 GSerg



Вопросов: 0
Ответов: 1876


 Профиль | | #7 Добавлено: 05.11.05 19:52
У меня через ADO 15 секунд, с хранимой процедурой...

Ответить

Номер ответа: 8
Автор ответа:
 Pantalone



Вопросов: 32
Ответов: 104
 Профиль | | #8 Добавлено: 05.11.05 20:00
Если не сложно, объясни пожалуйста как реализовать хранимую процедуру в Access?

Ответить

Номер ответа: 9
Автор ответа:
 GSerg



Вопросов: 0
Ответов: 1876


 Профиль | | #9 Добавлено: 05.11.05 20:34
См. ответ номер 5.

Ответить

Номер ответа: 10
Автор ответа:
 EROS



Вопросов: 58
Ответов: 4255
 Профиль | | #10 Добавлено: 05.11.05 23:02
Говорят с если прога работает на DAO то часто бывают проблемы с установкой ее на другие компы


Все это гнусная ложь и провокации!! ).Много лет использовал именно её,пока не перешел на NET, и ни разу не было никаких проблем с установкой. Вся фишка в том,что DAO несколько "легче" ADO, которая в основном используются для сетевых версий. А для локальных версий на мой взгляд все же предпочтительней использовать DAO. (ИМХО) И кстати,раз уж ты занялся тестированием, то как вариант попробуй еще DAO+хранимая процедура.

Ответить

Номер ответа: 11
Автор ответа:
 Pantalone



Вопросов: 32
Ответов: 104
 Профиль | | #11 Добавлено: 05.11.05 23:20
EROS
DAO+хранимая как выглядит примерчик не кинешь?
Кстати, что интересно, делал дистрибутив через Setup Factory 5, так для DAO она из VB проекта сама отобрала кучку библиотек, а для ADO помимо того что отобрала так еще и про MDAC заикнулась что де надо бы вот его включить тоже, я немного не понял, для DAO она игнорирует что ли MDAC?

Ответить

Номер ответа: 12
Автор ответа:
 GSerg



Вопросов: 0
Ответов: 1876


 Профиль | | #12 Добавлено: 05.11.05 23:24
MDAC включает в себя DAO 2.5/3.5, 3.51, 3.6.
Что делает Setup Factory, я не знаю.

Ответить

Номер ответа: 13
Автор ответа:
 Pantalone



Вопросов: 32
Ответов: 104
 Профиль | | #13 Добавлено: 06.11.05 00:30
Setup Factory про MDAC ни слова ни сказал, отобрал какую-то тучу библиотек на 6 мегов и запаковал. На 98 встало и заработало нормально.

Ответить

Номер ответа: 14
Автор ответа:
 EROS



Вопросов: 58
Ответов: 4255
 Профиль | | #14 Добавлено: 06.11.05 18:23
Сделать наглядный пример,к сожалению не могу, так как нет под рукой VB6. Могу лишь предложить фрагмент кода из одного моего тестового проекта,где показано как вызывать хранимую процедуру через QueryDefs,используя DAO. А создать саму хранимку можешь с помощью того же Access или же использовать готовую от GSerg
 из ответа №5. Разумеется сам пример переделаешь как надо.

'Referens:
'- DAO 3.6
'- Excel 8.0 or later
Option Explicit
 Dim db As DAO.Database
 Dim rs As DAO.Recordset
 Dim Qry As DAO.QueryDef
Private Sub Command1_Click()
    Dim i As Integer
    Dim colcount As Integer
    Dim rowcount As Integer
    Dim objExcel As Excel.Application
    Screen.MousePointer = vbHourglass
    Set db = OpenDatabase(App.Path & "\db1.mdb";)
    Set Qry = db.QueryDefs("AllSclad";) 'AllSclad-имя запроса предварительно сохранённого в базе данных
    Set rs = Qry.OpenRecordset()
    colcount = rs.Fields.Count - 1
    rowcount = rs.RecordCount
    Set objExcel = New Excel.Application
    objExcel.SheetsInNewWorkbook = 1
    objExcel.Workbooks.Add
    With objExcel.ActiveWorkbook.ActiveSheet
        For i = 0 To rs.Fields.Count - 1
            .Cells(1, i + 1) = rs.Fields(i).Name 'заполняем заголовки столбцов
        Next i
        .Range("A1:" & Chr$(65 + colcount) & "1";).Font.Bold = True
        .Range("A1:" & Chr$(65 + colcount) & "1";).Borders(xlEdgeBottom).LineStyle = xlDouble
        .Range("A1:" & Chr$(65 + colcount) & "1";).HorizontalAlignment = xlCenter
    '*******************************************************
    'копируем наш набор записей rs начиная с позиции "A2"
    'работает на порядок быстрее чем метод перебора строк
    'и столбцов во вложенном цикле
        .Range("A2";).CopyFromRecordset rs
    'Сань,вся фишка в строке выше! Как ты заметил
    'метод CopyFromRecordset объекта Sheet Одним махом
    'заполняет лист Excel данными.БЕЗ ЦИКЛОВ!!!
    '*******************************************************
        .Range(";D:E";).NumberFormat = "0.0000"
        .Range("B:C";).HorizontalAlignment = xlCenter
        .Range(Chr$(65 + colcount) & CStr(rowcount + 2)).FormulaR1C1 = "=SUM(R[-" & rowcount + 1 & "]C:R[-1]C)"
        .Range("A" & CStr(rowcount + 2)) = "ИТОГО НА СУММУ:"
        .Range("A" & CStr(rowcount + 2) & ":" & Chr$(65 + colcount) & CStr(rowcount + 2)).Font.Bold = True
        .Range("A" & CStr(rowcount + 1) & ":" & Chr$(65 + colcount) & CStr(rowcount + 1)).Borders(xlEdgeBottom).LineStyle = xlDouble
        .Cells(1, 1).CurrentRegion.EntireColumn.AutoFit 'регулирует ширину столбцов
        .Name = "Остатки по складу на " & FormatDateTime(Date, vbShortDate)
        .Range("A2";).Select
        objExcel.Windows(1).FreezePanes = True
        .Range("G5";).Select
    End With
    Screen.MousePointer = vbDefault
    With objExcel
        .Visible = True
    End With
    Set objExcel = Nothing
    db.Close
End Sub
Private Sub Form_Unload(Cancel As Integer)
    Set db = Nothing
    Set rs = Nothing
    Set Qry = Nothing
End Sub

Ответить

Страница: 1 |

Поиск по форуму



© Copyright 2002-2011 VBNet.RU | Пишите нам