我最近开始在一个大政府组织工作。我学习了软件开发4年。在那段时间里,我们浏览了基本的旧学校数据库使用和数据库优先设计,并且我可以编写一个基本查询,但是我们没有进入非常复杂的数据库设计。我们更专注于新技术,如代码第一个实体框架和模型的第一等查询和老学校数据库的复杂性
现在,在我组织的各种IT策略只是使得使用是不可能的工艺和技术的任何变化或进步。就在今天早上,我收到了一个工作请求,以解决从数据库调用信息的Web应用程序超时的问题。我很快确定网页的代码隐藏是调用一个查询超过200k条记录的表的存储过程,所以我打开它来试试看看我能否评估过程的效率。
该过程的复杂性远远超出我的能力,以重现,几乎过于复杂,即使明白了!我让DB管理员通过向表添加索引来帮助我,所以我不会在这里要求技术解决方案。接下来,看看有问题的存储过程之前,我继续:
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的工具?
男人,你在哪里学习?首先,这不是一个超级复杂的SP(并且200.000行很小)。其次,为了学习4年而不学习如何使用数据库(并且不,实体框架/代码优先不是学习基本SQL的替代品)是浪费时间。在EF中你甚至无法表达你可以用SQL来做的很多事情。按照大多数标准,上述是一个基本查询。不是“完全初学者无线索SQL”查询,但也不是那么复杂。 – TomTom
哦,还有一件事。这个查询的复杂性与“老派”没有任何关系。在EF中你会有类似的复杂性。这意味着“你在4年内从来没有做过非常微不足道的查询”。即使使用EF,您最终可能会加入十几张表格,并拥有一两个条件。 – TomTom