2014-02-10 44 views
0

我最近开始在一个大政府组织工作。我学习了软件开发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的工具?

+0

男人,你在哪里学习?首先,这不是一个超级复杂的SP(并且200.000行很小)。其次,为了学习4年而不学习如何使用数据库(并且不,实体框架/代码优先不是学习基本SQL的替代品)是浪费时间。在EF中你甚至无法表达你可以用SQL来做的很多事情。按照大多数标准,上述是一个基本查询。不是“完全初学者无线索SQL”查询,但也不是那么复杂。 – TomTom

+0

哦,还有一件事。这个查询的复杂性与“老派”没有任何关系。在EF中你会有类似的复杂性。这意味着“你在4年内从来没有做过非常微不足道的查询”。即使使用EF,您最终可能会加入十几张表格,并拥有一两个条件。 – TomTom

回答

1

这看起来像一个典型的过程。这可能是手写的。

的过程似乎是在做基于多个搜索参数(可能是从应用程序中的搜索表单)的搜索。

这种查询通常很难优化,因为它缺乏一个关键搜索词(或在不同的调用不同的关键搜索词)。

这个特定查询的最佳优化可能会是一个全表扫描,所以检查是否有指标最近已加入并尝试删除它们。请注意,索引可能是由于某个原因而添加的,因此删除索引可能会在应用程序的其他部分引入性能问题。

如果失败,您应该检查查询计划。

1

其实没有,这里有严重的问题。

首先,请提供queryp lan。

但其次 - WITH RECOMPILE提示是必要的。这个SP根据参数有很多不同的查询路径,但这不是表达式 - 第一个调用将决定查询路径,无论多么明智。标准(基本知识)解决方法是向查询添加提示以优化哪些内容 - 或者编译器不重用计划,这是WITH RECOMPILE的作用。

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

这不是老同学 - 对不起。这种类型的SP在15年前烂了。这是一个更高层次的查询框架的亮点(EF/LINQ是一个,但嘿,我在1990年左右使用类似的东西,没有开玩笑,所以不要说“现代”的东西比你学习编程的时间要长)。SQL - 特别是在SP中 - 很难处理可变的查询需求。