Этот баннер — требование Роскомнадзора для исполнения 152 ФЗ.
«На сайте осуществляется обработка файлов cookie, необходимых для работы сайта, а также для анализа использования сайта и улучшения предоставляемых сервисов с использованием метрической программы Яндекс.Метрика. Продолжая использовать сайт, вы даёте согласие с использованием данных технологий».
Политика конфиденциальности
|
|
|
Оптимизация SELECT
|
|||
|---|---|---|---|
|
#18+
Добрый день, уважаемые! Сразу сорри за большое количество кода, но возник такой вопрос - есть сложная процедура поиска по базе... Записи возвращаются клиенту на запрошенном языке. Так вот - на кол-ве записей в основной таблице около 30000 процедура отрабатывает около 2 секунд. Хотелось бы узнать мнение гуру, взглянувших на ниже приведенный код - а можно-ли увеличить скорость исполнения? Я и так парился с ней около недели, но заказчик недоволен... Итак, код в студию: CREATE PROCEDURE dbo.sp_Search @Country int, --страна, если неважно - 0 @Sex int, --пол - 2(мужчина) или 3(женшина) @Ageot int,--возраст от (0 или выбранная цифирь) @Agedo int,--возраст до (120 или выбранная цифирь) @Rostot int, --рост от (0 или выбранная цифирь) @Rostdo int, --рост до (300 или выбранная цифирь) @Massot int, --масса от (0 или выбранная цифирь) @Massdo int, --масса до (300 или выбранная цифирь) @Eyecolor int,--цвет глаз (0 - неважно) @Haircolor int,--цвет волос (0 - неважно) @LangID int, --на каком языке выдавать фразы (1-русский, 2-английский, 3-испанский) @RecordsPerPage int,--количество записей на странице @FromRec int,--с какой записи выдавать @NewFromDay int =0,--новые за (10000 - неважно, 7 - неделя, 30 - месяц, 1 - день) @Photoonly int=0 -- только с фото? 0 - неважно, -1(минус 1) - без фото, 1 - только с фото AS CREATE TABLE #Results -- создаем временную таблицу ( OwnerID int,--ИД юзера LangID int,--ИД его родного языка Country varchar(100), -- Название его страны CountryID int,-- ИД его страны ClName varchar(50),--имя юзера Age int,--возраст Rost int,--рост Mass int,--вес EyeID int,--ИД цвета глаз HairID int,--ИД цвета водос Eyecolor varchar(100),--название цвета глаз Haircolor varchar(100),--название цвета волос Nature varchar(100),--натура YNat int,--ИД натуры Zod int,--ИД знака зодиака Zodiac varchar(100),--знак зодиака (фраза) Photo varchar(200),--путь к фото PhotoGud int,--0 - плохое фото, 1 - хорошее Ord int -- порядковый номер записи ) DECLARE @i int -- декларируем переменную-счетчик SET @i=0 -- и выставляем ее в 0 INSERT INTO #Results --вставляем во временную таблицу записи согласно выбранным критериям (OwnerID,LangID,Age, Rost, Mass,CountryID, Photo, PhotoGud, EyeID, HairID,YNat, Zod) -- селектим только ID из анкеты (цвет глаз там и пр.) для ускорения выборки. Фразы будем селектить только для малой части записей SELECT cl.OwnerID,cl.LangID,cl.YearsOld, cl.Rost, cl.Mass,cl.CountryID,cl.OwnerPhotoName,cl.OwnerPhotoIsGud, an.EyeColor, an.HairColor,an.YouNature1, an.Zodiac FROM Clients cl JOIN Ankets an ON ( an.OwnerID=cl.OwnerID ) --ИД анкеты должно быть равно ИД клиента WHERE cl.OwnerIsActive=1 --юзер должен быть активным AND cl.Sex=@Sex --пол по переданному параметру AND (cl.YearsOld BETWEEN @Ageot AND @Agedo) --попадание в промежуток возраста AND cl.RegistrationDate > DATEDIFF(dy,@NewFromDay,GETDATE()) -- когда зарегистрировался (это для "Новые за:"). --Поэтому и @NewFromDay=10000 если неважно (типа, за последние 3 года)... AND (cl.Rost BETWEEN @Rostot AND @Rostdo) --попадание в промежуток роста AND (cl.Mass BETWEEN @Massot AND @Massdo) -- попадание в промежуток массы AND cl.CountryID= case --смотрим, указали ли страну when @Country =0 then cl.CountryID -- если 0 (неважно), тогда поле должно быть равно самому себе ) when @Country >0 then @Country -- иначе указанной стране end AND cl.OwnerPhotoIsGud>=@Photoonly AND cl.OwnerPhotoIsGud <= @Photoonly+1 -- смотрим, чтобы фото было по переданным параметрам AND an.EyeColor= case -- цвет глаз when @Eyecolor=0 then an.EyeColor -- если 0 (неважно), то самому себе when @Eyecolor>0 then @Eyecolor -- иначе переданному параметру end AND an.HairColor = case --цвет волос when @Haircolor=0 then an.HairColor -- если 0 (неважно), то самому себе when @Haircolor>0 then @Haircolor -- иначе переданному параметру end ORDER BY cl.OwnerPhotoIsGud DESC,cl.OwnerID DESC -- ну и упорядочиваем по фото и ИД юзера UPDATE #Results SET @i=@i+1, Ord=@i -- нумеруем все записи от 1 до конца --Далее вставляем во временную таблицу фразы из таблицы "Фразы" с таким условием: -- фраза должна быть на выбранном языке -- фраза должна быть вставлена только в записи, попадающие в нужный промежуток -- 44 - это ИД фразы, общей для обеих полов (для мужиков и баб) UPDATE #Results SET Eyecolor= cl.Phraze FROM #Results JOIN Phrases cl on cl.PhraseID=#Results.EyeID AND cl.LangID=@LangID AND (cl.SexID=@Sex OR cl.SexID=44) AND (#Results.Ord>=@FromRec AND #Results.Ord <= @RecordsPerPage+@FromRec) UPDATE #Results SET Haircolor= cl.Phraze FROM #Results JOIN Phrases cl on cl.PhraseID=#Results.HairID AND cl.LangID=@LangID AND (cl.SexID=@Sex OR cl.SexID=44) AND (#Results.Ord>=@FromRec AND #Results.Ord <= @RecordsPerPage+@FromRec) UPDATE #Results SET Nature= cl.Phraze FROM #Results JOIN Phrases cl on cl.PhraseID=#Results.YNat AND cl.LangID=@LangID AND (cl.SexID=@Sex OR cl.SexID=44) AND(#Results.Ord>=@FromRec AND #Results.Ord <= @RecordsPerPage+@FromRec) UPDATE #Results SET Zodiac= cl.Phraze FROM #Results JOIN Phrases cl on cl.PhraseID=#Results.Zod AND cl.LangID=@LangID AND (cl.SexID=@Sex OR cl.SexID=44) AND (#Results.Ord>=@FromRec AND #Results.Ord <= @RecordsPerPage+@FromRec) UPDATE #Results SET ClName= cl.ClientName FROM #Results JOIN ClientNames cl on cl.OwnerID=#Results.OwnerID AND (#Results.Ord>=@FromRec AND #Results.Ord <= @RecordsPerPage+@FromRec) -- Вставляем названия стран клиентов UPDATE #Results SET Country= cl.CountryName FROM #Results JOIN CountryList cl on cl.CountryID=#Results.CountryID AND cl.LangID=@LangID AND (#Results.Ord>=@FromRec AND #Results.Ord <= @RecordsPerPage+@FromRec) DECLARE @Total int -- декларирует переменную, содержащую общее количество найденных записей SELECT @Total = (SELECT COUNT(OwnerID) FROM #Results) -- и присваиваем ей количество найденных записей SELECT @Total AS TotalRecs -- селектим ее в скрипт -- селектим все записи, подпадающие под выбранный промежуток SELECT OwnerID,Country,ClName,Age,Rost,Mass,Eyecolor,Haircolor,Nature,Zodiac,Photo,PhotoGud FROM #Results WHERE #Results.Ord>=@FromRec AND #Results.Ord <= @RecordsPerPage+@FromRec ORDER BY Ord В результате работы процедуры самая дорогостоящая выборка - это первый селект во временную таблицу. Чем меньше задано критериев отбора - тем медленнее процедура работает. Вопрос для тех, кто просмотрел до сюда - итак, как же все таки сделать это добро работающим быстрее? Премного благодарен заранее... С уважением, Дмитрий. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 28.01.2002, 14:54 |
|
||
|
Оптимизация SELECT
|
|||
|---|---|---|---|
|
#18+
Навскидку 1.Вместо перенумерации после 1 выборки лучше всего во временной таблице #Results к полю Ord добавить identity(1, 1) primary key. Замечено, что добавление в таблицу, где отсутствует основной ключ происходит значительно медленнее, во вторых Вы сразу же получаете нумерацию. 2. Вместо выражения типа: AND an.HairColor = case --цвет волос when @Haircolor=0 then an.HairColor -- если 0 (неважно), то самому себе when @Haircolor>0 then @Haircolor мне кажется было бы удачнее следующее: AND (@Haircolor=0 OR an.HairColor = @Haircolor) Пока, надеюсь достаточно Надеюсь индексы в исходной таблице по поисковым полям есть ? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 28.01.2002, 15:42 |
|
||
|
Оптимизация SELECT
|
|||
|---|---|---|---|
|
#18+
В дополнение: Если Вы пользуетесь MS SQL Server 2000, то вместо временной таблицы используйте переменную типа TABLE. Конечно, в ней должен быть кластерный первичный ключ. Везде, где имеет смысл, не забывайте обьъявлять поля NOT NULL. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 28.01.2002, 15:55 |
|
||
|
|

start [/forum/topic.php?fid=46&msg=32021715&tid=1824151]: |
0ms |
get settings: |
9ms |
get forum list: |
16ms |
check forum access: |
4ms |
check topic access: |
4ms |
track hit: |
91ms |
get topic data: |
11ms |
get forum data: |
3ms |
get page messages: |
50ms |
get tp. blocked users: |
1ms |
| others: | 257ms |
| total: | 446ms |

| 0 / 0 |
