Страница: 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 строк в ту же таблицу занимает пару-тройку секунд?
Ответить
|
Номер ответа: 2 Автор ответа: Pantalone
Вопросов: 32 Ответов: 104
|
Профиль | | #2
|
Добавлено: 04.11.05 23:59
|
С текстовым файлом некрасиво как-то.
Можно по 5 пункту немного подробнее?
Забыл сказать что работа в VB6
Ответить
|
Номер ответа: 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 ata 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 связываться. Теперь сижу репу чешу.
Ответить
|
Номер ответа: 8 Автор ответа: Pantalone
Вопросов: 32 Ответов: 104
|
Профиль | | #8
|
Добавлено: 05.11.05 20:00
|
Если не сложно, объясни пожалуйста как реализовать хранимую процедуру в Access?
Ответить
|
Номер ответа: 11 Автор ответа: Pantalone
Вопросов: 32 Ответов: 104
|
Профиль | | #11
|
Добавлено: 05.11.05 23:20
|
EROS
DAO+хранимая как выглядит примерчик не кинешь?
Кстати, что интересно, делал дистрибутив через Setup Factory 5, так для DAO она из VB проекта сама отобрала кучку библиотек, а для ADO помимо того что отобрала так еще и про MDAC заикнулась что де надо бы вот его включить тоже, я немного не понял, для DAO она игнорирует что ли MDAC?
Ответить
|
Номер ответа: 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(" :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 |
Поиск по форуму