2011-09-14 6 views
1

나는 Excel 프로젝트와 함께 가구의 평화를 계산하는 데 도움이되고 있습니다. 첫 번째 작업은 데이터베이스에서 모든 자료를 선택하는 것입니다. 액세스 MDB 파일을 조회하는 동안 VBA : 서버에서 Excel로 액세스 쿼리

Sub Material_search() 
Dim cnt  As New ADODB.connection 
Dim rst  As New ADODB.Recordset 
Dim rcArray As Variant 
Dim sSQL As String 
Dim db_path As String, db_conn As String 
Dim item As String 

item = Replace(TextBox1.Text, " ", "%")  ' Search word 
sSQL = "Select Data, NomNr, Preke, Matas, Kaina, Tiek from VazPirkPrekes " & _ 
     "Where VazPirkPrekes.PirkVazID IN (SELECT VazPirkimo.PirkVazID FROM VazPirkimo Where VazPirkimo.Sandelys like '%ALIAVOS')" & _ 
     " and Year(VazPirkPrekes.Data)>=2011 and Preke Like '%" + item + "%' and Kaina > 0" & _ 
     " Order by Preke, Data Desc" 
db_path = Sheets("TMP").Range("B6").value 
db_conn = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & db_path & ";" 
cnt.Open db_conn 
rst.Open sSQL, cnt, adOpenForwardOnly, adLockReadOnly 
ListBox1.Clear 
If Not rst.EOF Then 
    rcArray = (rst.GetRows) 
    rcArray = WorksheetFunction.Transpose(rcArray) 
    Dim a As Variant 
    With ListBox1 
     .ColumnCount = 6 
     .list = rcArray 
     .ListIndex = -1 
    End With 
End If 
rst.Close: Set rst = Nothing 
cnt.Close: Set cnt = Nothing 
Label4.Caption = UBound(ListBox1.list) + 1 
End Sub 


최근에 내가 몇 가지 문제를 내놓았다 : 이 코드입니다. 문제는 데이터베이스 파일이 로컬 디스크에있을 때 검색이 매우 빠르게 작동하지만 데이터베이스 파일을 서버에 넣을 때 검색이 10 배 이상 길어지기 때문에 적합하지 않습니다.

이 코드에 대한 최적화가 있습니까? 아니면 그 쿼리가 액세스 '데이터베이스 엔진이 두 테이블에서 모든 190K 행을 검색해야하는 서버 문제를 사전

+0

코드를 최적화했다하더라도 - 그것은 할 수있다 염치 - - 문제는 원격 쿼리입니다. 네트워크 속도, 대기 시간 또는 Access가이 용도로 설계되지 않았기 때문일 수 있습니다 ... Access에 액세스 할 수없고 더 많은 용도로 사용할 수없는 경우 쿼리를 매개 변수화하고 Access에 저장할 수 있습니다. Excel 프로젝트에서 원격으로 호출 할 수 있습니다. 비록, 나는 여전히 차이가별로 없을 것이라고 생각합니다 : P – Xophmeister

+1

일반적인 문제는 긴 경로입니다. 매핑 된 드라이브를 사용해 보셨습니까? – Fionnuala

+1

@Xophmeister 액세스는 서버에서 정상적으로 작동하며 수년간 사용해 왔습니다. 이것을 위해 설계되었습니다. 다중 사용자 환경에서 백엔드가 서버에서 사용되고 프론트 엔드가 사용자 PC에서 사용되는 것이 좋습니다 Microsoft 문서를 확인하십시오. – Fionnuala

답변

1

에서

감사합니다. 느린 속도는 당연한 일이며, db 엔진이 네트워크를 통해 2 * 190K 행을 검색해야 할 때 속도가 느려집니다.

TextBox1.Text는 "foo는"이 포함 된 경우

, 이것은 당신이 실행하는 DB 엔진을 요구하고있는 문이다 : 그것은 결정하기 전에

Select Data, NomNr, Preke, Matas, Kaina, Tiek 
from VazPirkPrekes 
Where 
    VazPirkPrekes.PirkVazID IN (
     SELECT VazPirkimo.PirkVazID 
     FROM VazPirkimo 
     Where VazPirkimo.Sandelys like '%ALIAVOS') 
    and Year(VazPirkPrekes.Data)>=2011 
    and Preke Like '%foo%' 
    and Kaina > 0 
Order by Preke, Data Desc 

엔진은 VazPirkimo 테이블에서 모든 190K 행을 검색해야합니다은 그 중 "ALIAVOS"로 끝나는 Sandelys 값이 포함됩니다. 선택 기준이 인 값이 "ALIAVOS"인 경우 엔진은 Sandelys의 인덱스를 사용하여 VazPirkimo에서 검색해야하는 행 수를 제한 할 수 있습니다. 그러나, 그 접근 방식은 아마 당신을위한 옵션이 아니므로, VazPirkimo에 숫자 필드 인 Sandelys_group을 추가하고 Sandelys_group에 대한 색인을 생성하는 것을 고려하십시오. Sandelys가 "ALIAVOS"로 끝나는 모든 행에 동일한 Sandelys_group 번호 (1)를 지정하십시오. 그런 다음 "IN()"조건이 될 수있다 :

SELECT VazPirkimo.PirkVazID 
FROM VazPirkimo 
Where VazPirkimo.Sandelys_group = 1 

Sandelys_group의 인덱스는 DB 엔진이 희망 테이블의 190K 행의 작은 하위 집합에만 일치하는 행을 검색 할 수 있습니다.

쿼리 속도를 높이려면 다른 변경 사항이 있습니다. 이 데이터에 대한 인덱스와 함께 2011 년부터입니다 그들의 결정하기 전에 DB 엔진이 VazPirkPrekes의 모든 190K 행을 검색하기 위해 강제로

Year(VazPirkPrekes.Data)>=2011 

,이 훨씬 더 빨리해야한다 : 당신의 WHERE 절에서이 기준 봐 : Preke 및 데이터에 대한 인덱스 구걸 BY

Kaina > 0 

귀하의 주문 : 기준이 Kaina에 인덱스로 빨라집니다

VazPirkPrekes.Data >= #2011-01-01# AND VazPirkPrekes.Data < #2012-01-01# 

이.

Order by Preke, Data Desc 

변경 사항 중 일부 또는 전부는 쿼리 속도를 높이는 데 도움이 될 수 있지만 그 정도는 알 수 없습니다. 살인자는 다음과 같습니다.

여기의 문제는 "Sandelys like"비교의 문제와 유사합니다.이 명령은 Preke가 "foo"로 시작하는 대신 "foo"를 포함하는 행을 요구하기 때문에 db 엔진은 Preke의 인덱스를 사용하여 일치하는 행만 검색 할 수 없습니다. 일치하는 항목을 찾기 위해 190K VazPirkPrekes 행을 모두 검색해야합니다. 이 기준에 대해 다른 기준을 사용할 수 없다면 쿼리 속도를 어느 정도 향상시킬 수 있는지가 제한됩니다.

+1

원본 WHERE 절에는 sargable 기준이 하나 있으므로 'Kaina'필드가 인덱싱 된 것으로 가정하면 전체 테이블을 가져 오지 않습니다. 그러나 당신의 다른 모든 관찰들이 자리하고 있습니다. –

0

최적화 도움말 주셔서 감사하지만 내가 서버에 데이터베이스 파일을 넣을 때만 문제가 발생한다고 말한 것입니다. 그리고 최적화가별로 도움이되지 않습니다. 그러나 나는 다른 생각을 생각했다.

빈 여백 검색은 약 40KB 레코드를 반환합니다.이 레코드는 필요한 모든 것을 포함합니다. 따라서 모든 레코드를 workbook_activate 이벤트의 고유 한 시트에 넣은 다음 나중에 해당 시트에서만 쿼리를 수행 할 것입니다.

Sub Database_upload() 
    Application.DisplayAlerts = False 
    On Error Resume Next 
    Sheets("DATA_BASE").Delete 
    On Error GoTo 0 
    Application.DisplayAlerts = False 
    Sheets.Add 
    ActiveSheet.name = "DATA_BASE" 
    Sheets("DATA_BASE").Visible = False: Sheets("DARBALAUKIS").activate 
    Dim cnt  As New ADODB.connection 
    Dim rcArray As Variant 
    Dim sSQL As String 
    Dim db_path As String, db_conn As String 
    Dim item As String 
    Dim qQt As QueryTable 
    item = "" 'search for empty blanks 
    sSQL = "Select Data, NomNr, Preke, Matas, Kaina, Tiek from VazPirkPrekes " & _ 
     "Where VazPirkPrekes.PirkVazID IN (SELECT VazPirkimo.PirkVazID FROM VazPirkimo Where VazPirkimo.Sandelys like '%ALIAVOS')" & _ 
     " and Year(VazPirkPrekes.Data)>=2011 and Preke Like '%" + item + "%' and Kaina > 0" & _ 
     " Order by Preke, Data Desc" 

    db_path = Sheets("TMP").Range("B6").value 
    db_conn = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & db_path & ";" 

    db_conn = "ODBC;DSN=MS Access 97 Database;" 
    db_conn = db_conn & "DBQ=" & db_path 
    Set qQt = Sheets("Sheet1").QueryTables.Add(connection:=db_conn, Destination:=Sheets("Sheet1").Range("A1"), Sql:=sSQL) 
    qQt.Refresh BackgroundQuery:=False 
End Sub 

결과 :

프로그램 시작시 오래 걸리지 만 검색 시간이 허용됩니다 - 나를 위해 문제가 해결 :)

관련 문제