Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2002.10.21;
Скачать: CL | DM;

Вниз

Мастерам. Подскажите   Найти похожие ветки 

 
Tornado ©   (2002-09-27 09:25) [0]

Есть БД Access, более 300 000 записей. Выполняю запрос с помощью компонента ADOQuery. Запрос следующего вида:

DM1.ADOQuery1.SQL.Add("SELECT * FROM PEOPLE WHERE
NAME LIKE " + name_s + "AND STREET LIKE" + street_q + "AND DOM LIKE" + house + "AND KV LIKE" + kv + "AND TEL LIKE" + q_phone + "ORDER BY NAME");


где: name_s, street_q, house, kv, q_phone - переменные, получающие значения из текстовых полей, заполняемых пользователем. Поля в таблице все индексированы, имеется ключевое автоинкременентное поле ID.

Но запрос выполняется очень долго, порядка 6-7 сек на машине CPU 1000, ОЗУ 256 и т.д., боюсь представить что будет на более слабых машинах...Может можно как-то оптимизировать запрос или есть какие-то другие способы увеличить быстродействие, подскажите пожалуйста. Спасибо.


 
Johnmen ©   (2002-09-27 09:45) [1]

Не думаю, что всегда осуществляется поиск сразу по всем частично заданным значениям всех полей !
Посему : если не задано значение, так и не делай на соотв.поле LIKE ... в запросе.


 
Anatoly Podgoretsky ©   (2002-09-27 09:56) [2]

При таком количестве данных и с таким диким запросом, будь благодарен, что вообще выполняется за такое малое время


 
Tornado ©   (2002-09-27 13:22) [3]

ОК, согласен, запрос диковат, но тогда подскажите, уважаемые знатоки, как это сделать лучше? Примерчик если можно. Спасибо.


 
Johnmen ©   (2002-09-27 13:33) [4]

>Tornado © (27.09.02 13:22)
>...подскажите, уважаемые знатоки, как это сделать лучше?

Что получше ? И в каком смысле "получше" ?



 
ЮЮ ©   (2002-09-27 13:37) [5]

Посмотри, сколько выполняется запрос по самому существенному полю
SELECT * FROM PEOPLE WHERE NAME LIKE " + name_s
Если существенно быстрее, то затем делать подзапросы, т.е. проверку уже значительно меньшего объема:
SELECT * FROM
(SELECT * FROM PEOPLE WHERE NAME LIKE " + name_s) names
WHERE STREET LIKE" + street_q



 
BlackTiger   (2002-09-27 13:40) [6]

Ну, во-первых, сколько бы ты не индексировал, LIKE не будет использовать твои индексы. Индексы работают при ПРЯМОМ задании значений или при BETWEEN. И не делай LIKE сразу по всем полям, будет выполняться n-кратный "full scan", где n - количество полей.
Да и вообще, 6-7 секунд для такого запроса (а Акксессе) ЭТО ОЧЕНЬ БЫСТРО!
Хочешь быстрее - меняй технологию фильтрации на значения без маски (BETWEEN [...] AND [...]).


 
Tornado ©   (2002-09-27 15:03) [7]

> ЮЮ © (27.09.02 13:37)

Я зделал как Вы сказали, но запрос не работает. Что тут не так?

DM1.ADOQuery1.SQL.Add("SELECT * FROM");
DM1.ADOQuery1.SQL.Add("SELECT * FROM PEOPLE WHERE NAME LIKE " + name_s)name_s;
DM1.ADOQuery1.SQL.Add("WHERE STREET LIKE " + street_q);


Ошибка в предложении FROM


 
Johnmen ©   (2002-09-27 15:21) [8]

1. Проверь наличие скобочек в теле запроса
2. Такой синтаксис может не поддерживаться в Access


 
roottim   (2002-09-27 15:32) [9]

дело в том, что индексы не работают, если присутствует оператор LIKE..
здесь необходимо разделить поиск на точный и "неочень" :-)
использовать =, тогда сработают индексы..


 
Tornado ©   (2002-09-27 16:08) [10]

> roottim (27.09.02 15:32)

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

> Johnmen © (27.09.02 15:21)

Да, видимо скобки нужны в подзапросе, только где их ставить?
Access поддерживает подобные запросы вроде, в хелпе написано.
В принципе понятно, только вот с кавычками да скобками гемморой...


DM1.ADOQuery1.SQL.Add("SELECT * FROM");
DM1.ADOQuery1.SQL.Add("SELECT * FROM PEOPLE WHERE NAME LIKE " + name_s) names; {выделенное жирным - это что такое?}
DM1.ADOQuery1.SQL.Add("WHERE STREET LIKE " + street_q);


Помогите...


 
Johnmen ©   (2002-09-27 16:29) [11]

1.
DM1.ADOQuery1.SQL.Add("SELECT * FROM");
DM1.ADOQuery1.SQL.Add("((SELECT * FROM PEOPLE WHERE NAME LIKE " + name_s) names)"); {выделенное жирным - это что такое?}
DM1.ADOQuery1.SQL.Add("WHERE STREET LIKE " + street_q);
2. names - по-видимому, алиас для поля...



 
Johnmen ©   (2002-09-27 16:29) [12]

1.
DM1.ADOQuery1.SQL.Add("SELECT * FROM");
DM1.ADOQuery1.SQL.Add("((SELECT * FROM PEOPLE WHERE NAME LIKE " + name_s) names)"); {выделенное жирным - это что такое?}
DM1.ADOQuery1.SQL.Add("WHERE STREET LIKE " + street_q);
2. names - по-видимому, алиас для запроса...



 
BlackTiger   (2002-09-28 22:31) [13]

Ну, во-первых, "кавычки, кавычки и еще раз ... скобки".
Например нужно отобрать все, что содержит текст "ABC". Синтаксис такой:
SELECT * FROM Table WHERE Field LIKE "*ABC*" ORDER BY Field2.
Точнее для дельфы:
SQL.Add("SELECT * FROM Table WHERE Field1 LIKE ""*" + Edit1.Text+"*"" ORDER BY Field 2");
Если не LIKE почему-то не сработает, то либо меняй одинарные кавычки на двойные, либо используй функцию InStr:
SQL.Add("SELECT * FROM Table WHERE (InStr(Field1,""" + Edit1.Text + """,0)>0) ORDER BY Field2");

А о производительности в этом случае лучше позабыть. Либо удобства, либо производительность :-(


 
ЮЮ ©   (2002-09-30 04:52) [14]

SELECT * FROM
(SELECT * FROM PEOPLE WHERE NAME LIKE " + name_s) names
WHERE STREET LIKE" + street_q

names - это алиас для подзапроса. Синтаксис такой при использовании подзапросов. :-)

А по части использования BETWEEN или >= и <= для участия в подзапросе и того, что пользователь как правило будет вводить только часть искомого слова. Если ограничить пользователя тем, что он может искать только по началу поля, т.е. только по шаблону, например
STREET LIKE "Светлан%", то это равнозначно выражению
STREET BETWEEN "Светлан" AND "Светлан Я"


 
Психиатр ©   (2002-09-30 09:28) [15]

>ЮЮ © (30.09.02 04:52)
>STREET LIKE "Светлан%", то это равнозначно выражению
>STREET BETWEEN "Светлан" AND "СветланЯ"

Разве ? А как же "Светлан Я Пупкина" ?



 
Tornado ©   (2002-09-30 10:54) [16]

Я тут проверил, фильтр работает быстрее запроса...Может использовать фильтр? Что думают Мастера по этому поводу?

P.S. У меня есть программка, тел. справочник по Нижнему Новгороду, там очень итересно реализован запрос (или фильтр?), поиск занимает примерно 1, максимум 2 секунды, отображается прогресс баром и т.д. Прога написана толи на Дельфях, толи на C++ Builder. Првда имеет свой собственный формат БД с расширением *.phn. Записей тоже порядка 500 000, а размер всего лишь порядка 6 мег...Как это итнрнсно сднлано?


 
Desdechado ©   (2002-09-30 10:58) [17]

фильтр отрабатывает на клиенте, а запрос - на сервере. И что будет быстрее, зависит от многих условий.
Расширение можно любое приписать.


 
sniknik ©   (2002-09-30 12:07) [18]

лутшее решение уже прозвучало, использовать = вместо LIKE где возможно а где нет выбирать уже из подзапроса.
для интереса
запрос
SELECT * FROM 1saccsel
на таблице 418868 запись отрабатавает 18.32сек.

SELECT * FROM 1saccsel where Time = "BAOCGW"
на той же таблице возвращает 208зап за 1.94сек
с индексированным полем Time работает за 0.01сек !!!!!!

SELECT * FROM 1saccsel where Time LIKE "BAOCGW"
выполняется за 2.89сек
с индексированным полем Time ~ те же 2.75

выводы можно сделать. и фильтр не поможет т.к. выбрать все и отфильтровать нужное в моем случае горааааздо дольше. Использовал ADO,Jet база mdb ест-твенно локально.



Страницы: 1 вся ветка

Текущий архив: 2002.10.21;
Скачать: CL | DM;

Наверх




Память: 0.51 MB
Время: 0.021 c
1-68770
dimonf
2002-10-11 16:29
2002.10.21
Как изменить цвет активной ячейки DBGrid-a c синего на другой?


14-68959
kronprince
2002-09-27 13:10
2002.10.21
Подсел на песенку


14-69017
Gumanoid
2002-09-06 17:53
2002.10.21
Win ?????


4-69094
fishca
2002-09-05 17:20
2002.10.21
Руководство программиста


1-68708
Igorenius
2002-10-11 02:33
2002.10.21
Как правильно определить разрешение экрана??