Rambler's Top100
Форум: MS ACCESSVBVBA MS OfficeMS SQL server
Новые сообщения: 0000

Форум: MS ACCESS

Вопросы связанные с MS ACCESS

Обновить визитку
Участники «Online»
Все участники

 
 

Доброго времени суток, Посетитель!

вид форума:
Линейный форум Структурный форум

тема: Медленно выполняется запрос, хочется быстрее
 
 автор: krusz   (19.04.2012 в 11:28)   личное сообщение
 
 

есть запрос
"SELECT tabl.[nomertel], sum(tabl.[summazvonka]) FROM tabl WHERE tabl.[summazvonka]<>0 and (((tabl.[opisanie]) Like '*(РЕГ)*')) group by tabl.[nomertel] "

таблица tabl содержит более 2 000 000 записей.

запрос работает, но выполняется в течении 5-10минут. хочется быстрее.

  Ответить  
 
 автор: silich   (19.04.2012 в 12:29)   личное сообщение
 
 

null в summazvonka есть?
может их так nz([summazvonka],0)<>0 ?
или может вообще убрать?
всмысли хавингом потом, после суммирования?

или может сперва выборку сделать, а уже потом агрегацию?

а nomertel- ключевое? если нет, то может - сделать?

а opisanie не MEMO? то может если МЕМО, то instr, может, попробовать?
хотя лайк, вроде хорош....

  Ответить  
 
 автор: Krusz   (19.04.2012 в 14:07)   личное сообщение
 
 

если сделать выборку , и записать ее в таблицу , а потом делать агрегацию, то агрегация делается быстро.
но вот сама запись в таблицу заниает кучу времени около 5минут.
может я неправильно както записываю в таблицу?
подскажите как правильно рекордсет записать в таблицу? или ее вообще можно не записывать, а как то сам рекордсет суммировать?

  Ответить  
 
 автор: shanemac51   (19.04.2012 в 14:35)   личное сообщение
 
 


но вот сама запись в таблицу занимает кучу времени около 5минут.



--сколько записей выбирается 1-10-1000-10000

  Ответить  
 
 автор: Krusz   (19.04.2012 в 15:15)   личное сообщение
 
 

более 300 000 записей выбирается

  Ответить  
 
 автор: shanemac51   (19.04.2012 в 15:47)   личное сообщение
 
 

с повторными --300 000 записей
а уплотненных, с итогами

  Ответить  
 
 автор: Krusz   (19.04.2012 в 15:58)   личное сообщение
 
 

уплотненых с итогами уже порядка 150

  Ответить  
 
 автор: silich   (19.04.2012 в 15:01)   личное сообщение
 
 

insert - долго
create table - быстро

  Ответить  
 
 автор: Krusz   (19.04.2012 в 15:15)   личное сообщение
 
 

через create table я не знаю как вугрузить значения рекордсета, что то никакк не додумкаю.

  Ответить  
 
 автор: silich   (19.04.2012 в 15:46)   личное сообщение
 
 

аттачишь текстовый файл
и обращаешься к нему запросом

или, может ещё лучше(?надо проверять практически),
трансформ текстового файла сразу в таблицу акса

при условии, что данные в нормальном виде представлены

  Ответить  
 
 автор: Krusz   (19.04.2012 в 15:57)   личное сообщение
 
 

так и делаю, (еслия парвильно поянл) загружаю таблицу в отднельный файл акса, а далее уже из своего клиента к нему подключаюсь.

  Ответить  
 
 автор: Анатолий (Киев)   (19.04.2012 в 14:49)   личное сообщение
 
 


(tabl.[opisanie]) Like '*(РЕГ)*'

Тормоз здесь. А это "(РЕГ)" действительно в любой части текста? Что это обозначает? Как в таблицу вносятся записи? Может есть смысл добавить логическое или числовое поле для признака? Таблица родная или доступ по сети?

  Ответить  
 
 автор: silich   (19.04.2012 в 15:02)   личное сообщение
 
 

как думаешь, регекспом быстрее будет?
в оракле лайк шустр :)

  Ответить  
 
 автор: Krusz   (19.04.2012 в 15:26)   личное сообщение
 
 

таблицу присылает оператор связи (детализация всех звонков по всем абонентам более 2500абонентов), в текстовом формате.
(РЕГ) признак у них обозначает звонок во внутрисетевом роуминге, другого обозначения у них нет. впереди может быть еще один символ , он может быть любым
соответственно, я просто заливаю таблицу в аксес , а далее обрабатываю так как мне надо.
на самом деле если я сейчас научусь делать данную выборку быстро, у меня еще парочка запросов, котрые работают переделаются по данному алгоритму.

  Ответить  
 
 автор: snipe   (19.04.2012 в 17:00)   личное сообщение
 
 

может так (хотя не уверен)

SELECT t.nomertel AS Выражение1, (select sum ( r.summazvonka) as wer
from Tabl as r where r.nomertel=t.nomertel) AS сумма
FROM [SELECT s.nomertel
FROM Tabl as s
where s.opisanie like '*рег*']. AS t
GROUP BY t.nomertel
HAVING ((((select sum ( r.summazvonka) as wer
from Tabl as r where r.nomertel=t.nomertel))<>0))

  Ответить  
 
 автор: Krusz   (20.04.2012 в 15:01)   личное сообщение
 
 

тоже самое

  Ответить  
 
 автор: Анатолий (Киев)   (20.04.2012 в 14:13)   личное сообщение
 
 


я просто заливаю таблицу в аксес

Как заливаете? В существующую таблицу? Пустую?
Заливать можно запросом INSERT INTO, в нем добавить вычисляемое поле IIF(tabl.[opisanie]) Like '*(РЕГ)*', True, False), результат которого вносить в логическое поле таблицы. Ну или после импорта выполнить запрос UPDATE для этого поля.
А потом это поле использовать в условиях запроса.

  Ответить  
 
 автор: krusz   (20.04.2012 в 15:01)   личное сообщение
 
 

т.е. идея подготовить предварительно начальную табличку.
впринципе понятно. хотелось просто заливать талицу и работать, но раз нельзя значит нельзя

  Ответить  
 
 автор: snipe   (20.04.2012 в 15:41)   личное сообщение
 
 

Поэксперементировал
на 2 700 000 записях

тот запрос что я вам выше написал
отрабатывает у меня за 44 сек

запрос с которого начался топик - за 33 сек

запрос с дополнительным столбцом в таблице - за 19 сек

(основное время тратится на группировку почему-то)

  Ответить  
 
 автор: Анатолий (Киев)   (20.04.2012 в 19:29)   личное сообщение
 
 

А поле "nomertel" индексировано?

  Ответить  
 
 автор: Krusz   (23.04.2012 в 09:50)   личное сообщение
 
 

нет не индексированно. попробовал проиндексировать (с повторениями) но не особо быстро получилось.

  Ответить  
 
 автор: Krusz   (23.04.2012 в 09:54)   личное сообщение
 
 

вот просто выбрать нужные записи , вопросов нет, запрос отрабатывается быстро.
далее если записать выборку в темповую таблицу - здесь время уходит. , но зато потом операция с групировкой быстро отрабатывает.
и если делать сразу выборку с группировкой тоже время много уходит.

  Ответить  
 
 автор: shanemac51   (23.04.2012 в 11:40)   личное сообщение
 
 

--создайте пустую бд c:\pusto.mdb
--


filecopy c:\pusto.mdb c:\mrab1.mdb            
s1="select ......into rab1 in 'c:\mrab1.mdb'"
docmd.runsql s1


отчеты делать со связанной таблицы rab1
скорость выше, т.к. рабочая мдб --пустая

  Ответить  
 
 автор: Анатолий (Киев)   (20.04.2012 в 19:34)   личное сообщение
 
 


хотелось просто заливать талицу и работать

Ві не ответили ни на один мой вопрос.
Если "просто заливать талицу", то можно и не заливать, а прилинковать.
Если импортировать в новую таблицу, то после єтого можно в нее и индексы добавить, и поле, и заполнить это поле.
Но правильнее - заливать в заранее подготовленную таблицу.

  Ответить  
 
 автор: Krusz   (23.04.2012 в 09:49)   личное сообщение
 
 

Мне казалось, что выше есть ответы на эти вопросы.
я создаю файл mdb, туда импортирую данные в обычную таблицу. (просто импорт файла)
далее из клиента просто обращаюсь к этому файлу, и выбираю те данные, котрые мне нужны.

  Ответить  
 
 автор: silich   (23.04.2012 в 12:00)   личное сообщение
 
 

генератор ваших данных, например

'-- Task Tabl3K
Function rnd999()
Randomize
rnd999 = Int((999 * Rnd))
End Function

Function rnd99()
Randomize
rnd99 = Int((99 * Rnd))
End Function

Function rndAz(Optional upperbound = 254, _
               Optional lowerbound = 192, _
               Optional asChar As Boolean = True)
Dim ir&
On Error GoTo err123
Randomize
ir = CInt(Math.Round((upperbound - lowerbound + 1) * Rnd())) + lowerbound
If asChar Then
    rndAz = Chr(ir)
Else
    rndAz = CInt(ir) + lowerbound
End If
Exit Function
err123:
    rndAz = "#"
Exit Function
End Function

Function task_Tabl3k(Optional cRec& = 1, _
                     Optional dmode As Boolean = True)
Dim rs As DAO.Recordset
Dim i&, j&, ii&, s&, sr&, tel$, am@, note$
On Error GoTo err123
If cRec < 1 Then cRec = 1
If dmode = False Then CurrentDb.Execute "delete * from Tabl", dbFailOnError
SysCmd acSysCmdSetStatus, "заполнено: " & 0 & " из " & cRec
For i = 1 To cRec
    tel = "(" & Format(rnd99(), "000") & ")" & Format(rnd99(), "00") & "-" & Format(rnd999(), "000") & "-" & Format(rnd999(), "000")
    am = rnd99() / 100
    note = ""
    ii = CInt(Math.Round((50) * Rnd())) + 1
    For j = 0 To ii
        s = CInt(Math.Round((ii) * Rnd()))
        If s = 0 Then s = 1
        If j Mod s = 0 Then
            note = note & Chr(32)
        End If
        note = note & rndAz()
    Next j
    sr = (Math.Round((cRec - 1 + 1) * Rnd()))
    If sr > 0 Then
        If sr Mod 2 = 0 Then
            note = Replace(note, " ", "рег ")
        End If
    End If
    note = Left(LTrim(note), 255)
    If dmode = True Then
        Debug.Print "tel=" & tel, "am=" & am, "note=" & note
    Else
        CurrentDb.Execute "insert into Tabl(nomertel,summazvonka,opisanie) " & _
                          "values('" & tel & "'," & am & ",'" & note & "')", dbFailOnError
    End If
    SysCmd acSysCmdSetStatus, "заполнено: " & i & " из " & cRec: DoEvents
Next i
Exit Function
err123:
MsgBox Error, , "task_Tabl3k"
SysCmd acSysCmdClearStatus
Exit Function
End Function

пока заполняю таблицу 2мя миллионаме

  Ответить  
 
 автор: shanemac51   (23.04.2012 в 13:52)   личное сообщение
 
 

>пока заполняю таблицу 2мя миллионаме
------------------------
--заполнить мдб терпения не хватило
--создала текстовик
--прилинковала
--базовый запрос --21 секунда

SELECT [1256].tel, Sum([1256].am) AS [Sum-am], First([1256].note1) AS [First-note1]
FROM 1256
WHERE note1 like '*reg*' and am>0
GROUP BY [1256].tel;


похоже;причина замедления --размер мдб
--у меня он 700кб
--у вас видимо 700мб

запросы плохо работают при раздувании мдб

  Ответить  
 
 автор: silich   (23.04.2012 в 14:05)   личное сообщение
 
 

мне интересно было реализовать замысел по формированию псевдоданных :)

  Ответить  
 
 автор: shanemac51   (23.04.2012 в 15:33)   личное сообщение
 
 


''полной очистки от лишнего не делала, так немного
Function task_Tabl3kp(Optional cRec& = 1, _
                     Optional dmode As Boolean = True)
Dim rs As DAO.Recordset
Dim i&, j&, ii&, s&, sr&, tel$, am@, note$, s1, j2
'On Error GoTo err123
If cRec < 1 Then cRec = 1
If dmode = False Then CurrentDb.Execute "delete * from Tabl", dbFailOnError
SysCmd acSysCmdSetStatus, "заполнено: " & 0 & " из " & cRec
Open "c:\rab\1256.txt" For Output As #1
Print #1, "tel;am;note1"
j2 = 0
For i = 1 To cRec

    tel = "(" & Format(rnd99(), "000") & ")" & Format(rnd99(), "00") & "-" & Format(rnd999(), "000") & "-" & Format(rnd999(), "000")
    am = rnd99() / 100
    note = ""
    ii = CInt(Math.Round((30) * Rnd())) + 1
    For j = 0 To ii
        s1 = Chr(CInt(Math.Round((ii) * Rnd())) + 40)
        
        note = note & s1
        
     Next j
    'If InStr(note, "44") > 0 Then
    If note Like "*4*4*" Then
        note = note & "(reg) "
        j2 = j2 + 1
        If note > "999" Then
        Debug.Print "="; i; j2;
        End If
        End If
   
    If dmode = True Then
        'Debug.Print "tel=" & tel, "am=" & am, "note=" & note
        Print #1, tel, ";"; am; ";"; note
    Else
        CurrentDb.Execute "insert into Tabl(nomertel,summazvonka,opisanie) " & _
                          "values('" & tel & "'," & am & ",'" & note & "')"
                          ', dbFailOnError
    End If
'    Debug.Print acSysCmdSetStatus, "заполнено: " & i & " из " & cRec: DoEvents
    ' SysCmd
Next i
Close #1
Exit Function
err123:
MsgBox Error, , "task_Tabl3k"
SysCmd acSysCmdClearStatus
Exit Function
End Function

  Ответить  
 
 автор: Krusz   (23.04.2012 в 16:14)   личное сообщение
 
 

тут вы правы объем сразу после импорта таблицы более 1,3Гб. после сжатия около 950Мб.

  Ответить  
 
 автор: silich   (23.04.2012 в 16:28)   личное сообщение
 
 

в таблицу добавьте поле status
в котором будет 1 или 0 в зависимости от like "*рег*"

по этому полю сделайте индекс

на 2 000 000 записях у меня суммирование с группировкой по номеру телефона заняло порядка 40 секунд

  Ответить  
 
 автор: Krusz   (24.04.2012 в 11:04)   личное сообщение
 
 

уже тоже попробовал.
да чутток побыстрее стало, но блин сама операция на обновление поля status в зависимости от лайка тоже заняла доброе количество времени :). так что я подумал, пущай пользователи ждут окончания запроса. :) благо пользующихся данным запросом не так много. (ох уж эти бухгалтера)

  Ответить  
 
 автор: silich   (24.04.2012 в 12:20)   личное сообщение
 
 

значит надо поработать над алгоритмом(запросом) который бы быстро выставлял статус :)

например заливать(подготавливать) таблицу ночью :)
чтобы конечный пользователь мог работать с готовыми данными, не требующими дополнительной обработки
если это возможно, конечно

  Ответить  
 
 автор: shanemac51   (24.04.2012 в 11:14)   личное сообщение
 
 

>тут вы правы объем сразу после импорта таблицы более 1,3Гб. после сжатия около 950Мб.
-------------------------
таблица должна быть в другой базе--не программной
программная --не более 1-3 мб, таблица --линковка

  Ответить  
 
 автор: Krusz   (24.04.2012 в 11:42)   личное сообщение
 
 

так и есть.
один момент только хочу уточнить .
я не большой асс в программировании. поэтому по поводу линковки хотел бы уточнить.
я открываю таблицу следующим образом

Set db = DBEngine.Workspaces(0).OpenDatabase("путь к моей таблице в виде \\ser1\.....\....mdb")
Set RstKont = db.OpenRecordset("здесь мой запрос по группировке и суммированию")


может я не правильно делаю?

  Ответить  
 
 автор: shanemac51   (24.04.2012 в 11:50)   личное сообщение
 
 

каков объем программной базы

запрос --вроде все так, ошибки не замечаю
---но напишите полное имя, необязательно реальное
---главное чтобы пробелы,кавычки и слеши совпадали

"\\serv1\ddd\hhh hhhh hhhh\aaa.mdb"

--какой разделитель применяете в запросе

  Ответить  
 
 автор: Krusz   (24.04.2012 в 11:55)   личное сообщение
 
 

объем клиента 1,5Мб

у меня это все работает, вопрос не в этом. там ошибок не с раздилителями не с именами нет.
я просто подумал, может я не правильно понял и вы имели ввиду что-то другое под словом "линоквать"

  Ответить  
HiProg.com - Технологии программирования
Rambler's Top100 TopList