2014-02-10 2 views
0

Недавно я начал работать в большой правительственной организации. Я изучал разработку программного обеспечения в течение 4 лет. За это время мы взглянули на базовое использование старой базы данных и базовый дизайн базы данных, и я могу написать базовый запрос, но мы не входили в очень сложный дизайн базы данных. Мы больше сосредоточились на новых технологиях, таких как инфраструктура сущности кода и первая модель и т. Д.Сложность запросов и баз данных старой школы

Теперь различные ИТ-политики в моей организации практически делают невозможным любое изменение или продвижение технологий и технологий. Только сегодня утром я получил запрос на работу, чтобы решить проблему, когда веб-приложение, вызывающее информацию из базы данных, отключается. Я быстро решил, что код веб-страницы вызывает вызов хранимой процедуры, которая запрашивает таблицу с более чем 200 тыс. Записей, поэтому я открыл ее, чтобы проверить, могу ли я оценить эффективность процедуры.

Сложность процедуры - это путь, выходящий за пределы моих возможностей, для воспроизведения и почти слишком сложный, чтобы даже понять! У меня есть администратор базы данных, который помогает мне, добавив индексы в таблицы, поэтому я не буду просить о техническом решении здесь. Затем взгляните на хранимую процедуру, прежде чем продолжить:

CREATE PROCEDURE [dbo].[stp_RandomisationResultCount] 
    @noOfRows INT, 
    @subcouncil INT, 
    @wards VARCHAR(MAX) = NULL, 
    @suburbs VARCHAR(MAX) = NULL, 
    @courts VARCHAR(MAX) = NULL, 
    @skills VARCHAR(MAX) = NULL, 
    @isDisabled VARCHAR(1) = NULL, 
    @hasQualification VARCHAR(1) = NULL, 
    @gender VARCHAR(1) = NULL, 
    @age INT = NULL 
AS 
BEGIN 
SELECT COUNT(tblJobSeekerDetails.JobSeeker_ID) resultCount 
FROM tblJobSeekerDetails LEFT JOIN tbl_lnk_JobSeeker_OtherSkills 
ON tblJobSeekerDetails.JobSeeker_ID = tbl_lnk_JobSeeker_OtherSkills.JobSeeker_ID LEFT JOIN tblOtherSkills 
ON tbl_lnk_JobSeeker_OtherSkills.OtherSkillsID = tblOtherSkills.OtherSkillsID LEFT JOIN tblJobSeekerEmploymentHistory 
ON tblJobSeekerDetails.JobSeeker_ID = tblJobSeekerEmploymentHistory.JobSeekerID 
WHERE (tblJobSeekerDetails.SubCouncilID = @subcouncil) 
      AND ((WardID IN (SELECT s.Item      FROM ufn_SplitIntArray(@wards, ',') s)) OR (@wards IS NULL)) 
      AND ((Suburb IN (SELECT s.Item      FROM ufn_SplitIntArray(@suburbs, ',') s)) OR (@suburbs IS NULL)) 
      AND ((RoadType IN (SELECT s.Item FROM ufn_SplitIntArray(@courts, ',') s)) OR (@courts IS NULL)) 
      AND ((tblOtherSkills.OtherSkillsID in (SELECT s.Item FROM ufn_SplitIntArray(@skills, ',') s)) OR (@skills IS NULL)) 
      AND ((Disability = @isDisabled) OR (@isDisabled IS NULL)) 
      AND ((HasTertiaryQualification = @hasQualification) OR (@hasQualification IS NULL)) 
      AND ((Gender = @gender) OR (@gender IS NULL)) 
      AND ((ISNUMERIC(IdentityNumber) = 1 AND 
        IdentityNumber NOT LIKE '%.%' AND 
        DATEPART(YEAR, GETDATE()) - (CONVERT(INT, '19' + SUBSTRING(IdentityNumber, 1, 2), 100)) = @age) OR (@age IS NULL)) 
      AND (TypeID = 1)--Jobseekers only 
      AND (tblJobSeekerDetails.IsExcludedFromRandomisation <> 1 OR tblJobSeekerDetails.IsExcludedFromRandomisation IS NULL)--Explicitly excluded jobseekers 
      AND (tblJobSeekerDetails.JobSeeker_ID not in (SELECT DISTINCT tj.JobSeeker_ID --Exclude Jobseekers as per stipulated exclusion periods 
                  FROM tblJobSeekerDetails tj INNER JOIN tblJobSeekerEmploymentHistory wh 
                  ON tj.JobSeeker_ID = wh.JobSeekerID 
                  WHERE ((DATEDIFF(DAY, wh.DateOfEmploymentFrom, wh.DateOfEmploymentTo) <= 14 AND DATEDIFF(MONTH, wh.DateOfEmploymentTo, GETDATE()) <= 3)) 
                  OR 
                  ((DATEDIFF(DAY, wh.DateOfEmploymentFrom, wh.DateOfEmploymentTo) > 14 AND DATEDIFF(MONTH, wh.DateOfEmploymentTo, GETDATE()) BETWEEN 4 AND 6)) 
                  OR 
                  (GETDATE() BETWEEN wh.DateOfEmploymentFrom AND wh.DateOfEmploymentTo) 
                  OR (wh.DateOfEmploymentFrom > GETDATE() OR wh.DateOfEmploymentTo > GETDATE()) 
                  GROUP BY tj.JobSeeker_ID)) 
END 

Теперь этого достаточно, чтобы напугать меня. Я могу понять в общих чертах, что его должно было сделать, но сделать его более эффективным было бы невозможно для меня в настоящее время. Единственная причина, по которой меня попросили взглянуть на эту проблему, заключалась в том, что разработчик, ответственный за приложение, сегодня забронирован. Мой вопрос: это то, что обычно создается с помощью знаний sql разработчика или является каким-то инструментом, используемым для создания такого чудовищного sql?

+0

Человек, где вы учились? FIrst, который не является суперкомплексным SP (и 200 000 строк крошечным). Во-вторых, для изучения 4-х лет и не изучения того, как использовать базу данных (и нет, Entity Framework/Code First не являются заменой для изучения базового SQL) теряется впустую. Существует много вещей, которые вы даже не можете выразить в EF, которые вы можете сделать в SQL. По большинству стандартов это выше - основной запрос. Не запрос "total beginner no clue SQL", но и не такой сложный. – TomTom

+0

О, и еще одна вещь. Сложность этого запроса НИЧЕГО не связана с «старой школой». В EF у вас будет такая же сложность. Что переводится как «вы никогда не делали действительно больше, чем тривиальные запросы за 4 года». Даже используя EF, вы можете присоединиться к десяткам таблиц и иметь страницу или два условия. – TomTom

ответ

1

Это похоже на типичную процедуру. Вероятно, это было вручную.

Процедура, похоже, выполняет поиск по нескольким параметрам поиска (возможно, из формы поиска в приложении).

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

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

Если это не удается, вы должны проверить план запроса.

1

Фактически нет, здесь есть серьезные проблемы.

Во-первых, просьба предоставить запрос pan.

Но второй - с рекомендацией REOMPILE необходим. Этот SP имеет множество разных путей запроса в зависимости от параметров, но не выражен - первый вызов будет определять путь запроса, независимо от того, насколько он разумен. Стандартное (базовое знание) способ заключается в том, чтобы добавить подсказки к запросу, что оптимизировать для - или ell компилятор, чтобы не повторно использовать планы, что и делает с RECOMPILE.

http://technet.microsoft.com/en-us/library/ms181714.aspx

Это не старая школа - извините. Этот тип SP был гнилым 15 лет назад. Одно дело, когда любая структура запросов более высокого уровня сияет (EF/LINQ является одной, но эй, я использовал что-то похожее в 1990 году, не шучу, поэтому не говори «современное», что-то возвращается, дольше, чем вы изучали программирование).SQL - особенно в SP - трудно справиться с требованиями переменных запросов.

Смежные вопросы