2010-12-16 3 views
3

너희들은 훌륭하다. 지난 2 일간 새로운 사용자 인 두 번 게시했는데 도움을 받아서 날아갔습니다. 그래서, 내가 소프트웨어에서 얻은 가장 느린 쿼리를 가져다가 누군가가 내가 속도를 높이도록 도울 수 있는지를 알았습니다. 이 쿼리를 뷰로 사용하므로 쿼리가 빠르다는 점이 중요합니다.슈퍼 슬로우 쿼리 ... 내가 뭘 잘못 했니?

먼저 회사의 고객을 저장하는 연락처 테이블이 있습니다. 이 테이블에는 Contacts_Def_JobFunctions 테이블에 정의 된 ID를 포함하는 JobTitle 열이 있습니다. 또한 contact_link_job_functions라는 테이블이 있으며이 테이블에는 고객이 가지고있는 contactID 번호와 추가 작업 기능이 들어 있으며 Contacts_Def_JobFunctions 테이블에도 정의되어 있습니다.

두 번째로 Contacts_Def_JobFunctions 테이블 레코드는 자신과 부모/자식 관계를 가지고 있습니다. 이러한 방식으로 유사한 작업 기능 (예 : 가정부, 세탁 서비스, 관리, 청소 등 모든 기본 작업 - 직책이 다를 수 있음)을 클러스터링합니다. 현재 작업하지 않는 작업 기능은 ParentJobID 1841의 하위 항목으로 유지 관리됩니다.

셋째, 추가 코드 코드는 추가적으로 지리적 데이터를 제공하여 최종 결과를 제공합니다.

마지막으로 모든 책임 회사와 마찬가지로 Google은 수신 거부 한 후 Google 뉴스 레터 수신 거부를 원하는 고객에 대해 삭제 목록을 유지합니다.

나는 아래의 쿼리를 사용하여 뉴스 레터 수신을 선택한 사람과 우리가 제공하는 서비스/제품과 관련된 직무 또는 직위를 가진 사람들의 테이블을 작성합니다.

가 여기 내 UGLY 쿼리 : 나는 당신의 일부를 바라고 있어요

SELECT DISTINCT 
    dbo.contacts_link_emails.Email, dbo.contacts.ContactID, dbo.contacts.First AS ContactFirstName, dbo.contacts.Last AS ContactLastName, dbo.contacts.InstitutionID, 
    dbo.institutionswithzipcodesadditional.CountyID, dbo.institutionswithzipcodesadditional.StateID, dbo.institutionswithzipcodesadditional.DistrictID 
FROM   
    dbo.contacts_def_jobfunctions AS contacts_def_jobfunctions_3 
INNER JOIN 
    dbo.contacts 
INNER JOIN 
    dbo.contacts_link_emails 
     ON dbo.contacts.ContactID = dbo.contacts_link_emails.ContactID 
     ON contacts_def_jobfunctions_3.JobID = dbo.contacts.JobTitle 
INNER JOIN 
    dbo.institutionswithzipcodesadditional 
     ON dbo.contacts.InstitutionID = dbo.institutionswithzipcodesadditional.InstitutionID 
LEFT OUTER JOIN 
    dbo.contacts_def_jobfunctions 
INNER JOIN 
    dbo.contacts_link_jobfunctions 
     ON dbo.contacts_def_jobfunctions.JobID = dbo.contacts_link_jobfunctions.JobID 
     ON dbo.contacts.ContactID = dbo.contacts_link_jobfunctions.ContactID 
WHERE  
     (dbo.contacts.JobTitle IN 
     (SELECT  JobID 
     FROM   dbo.contacts_def_jobfunctions AS contacts_def_jobfunctions_1 
     WHERE  (ParentJobID <> '1841'))) 
    AND 
     (dbo.contacts_link_emails.Email NOT IN 
     (SELECT  EmailAddress 
     FROM   dbo.newsletterremovelist)) 
OR 
     (dbo.contacts_link_jobfunctions.JobID IN 
     (SELECT  JobID 
     FROM   dbo.contacts_def_jobfunctions AS contacts_def_jobfunctions_2 
     WHERE  (ParentJobID <> '1841'))) 
    AND 
     (dbo.contacts_link_emails.Email NOT IN 
     (SELECT  EmailAddress 
     FROM   dbo.newsletterremovelist AS newsletterremovelist)) 

슈퍼 스타는 나에게이 조정을 할 수 있습니다. 너무 많은

감사합니다,

러셀 SCHUTTE

UPDATE - UPDATE - UPDATE - UPDATE -

이 Khanzor에서 특히, 여러 피드백 메시지를받은 후, 나는 튜닝이 열심히 일했다

UPDATE 질의를하고 다음과 함께했습니다 :

SELECT DISTINCT 
        contacts_link_emails.Email, contacts.ContactID, contacts.First AS ContactFirstName, contacts.Last AS ContactLastName, contacts.InstitutionID, 
        institutionswithzipcodesadditional.CountyID, institutionswithzipcodesadditional.StateID, institutionswithzipcodesadditional.DistrictID 
FROM contacts 
INNER JOIN 
    contacts_def_jobfunctions ON contacts.jobtitle = contacts_def_jobfunctions.JobID AND contacts_def_jobfunctions.ParentJobID <> '1841' 
INNER JOIN 
    contacts_link_jobfunctions ON contacts_link_jobfunctions.JobID = contacts_def_jobfunctions.JobID AND contacts_def_jobfunctions.ParentJobID <> '1841' 
INNER JOIN 
    contacts_link_emails ON contacts.ContactID = contacts_link_emails.ContactID 
INNER JOIN 
    institutionswithzipcodesadditional ON contacts.InstitutionID = institutionswithzipcodesadditional.InstitutionID 
LEFT JOIN 
    newsletterremovelist ON newsletterremovelist.emailaddress = contacts_link_emails.email 
WHERE  
    newsletterremovelist.emailaddress IS NULL 

이것은 완벽하지 않습니다. oin 또는 권리 조인 또는 무엇인가, 그리고 나는 정말로 모른다). 내 결과 집합은 원래 쿼리가 제공 한 레코드의 약 40 %입니다 (더 이상 100 %는 완벽한 쿼리가 아닙니다).

일을 정리하기 위해 모든 "dbo"를 꺼 냈습니다. SQL Studio에 추가 된 접두사. 그들은 아무것도합니까?

지금 내가 뭘 잘못하고 있니?

감사

러셀 SCHUTTE

== == == == == == ANOTHER 업데이트 == ANOTHER 업데이트 == ANOTHER 업데이트 == ANOTHER 업데이트 == ANOTHER UPDATE에게 == == == == ==

저는 지금이 쿼리를 몇 시간 동안 작업 해 왔습니다.나는 이걸 가지고있다 :

SELECT DISTINCT 
         contacts_link_emails.Email, contacts.contactID, contacts.First AS ContactFirstName, contacts.Last AS ContactLastName, contacts.InstitutionID, 
         institutionswithzipcodesadditional.CountyID, institutionswithzipcodesadditional.StateID, institutionswithzipcodesadditional.DistrictID 
FROM   
    contacts INNER JOIN institutionswithzipcodesadditional 
     ON contacts.InstitutionID = institutionswithzipcodesadditional.InstitutionID 
    INNER JOIN contacts_link_emails 
     ON contacts.ContactID = contacts_link_emails.ContactID 
    LEFT OUTER JOIN contacts_def_jobfunctions 
     ON contacts.JobTitle = contacts_def_jobfunctions.JobID AND contacts_def_jobfunctions.ParentJobID <> '1841' 
    LEFT OUTER JOIN contacts_link_jobfunctions 
     ON contacts_link_jobfunctions.JobID = contacts_def_jobfunctions.JobID AND contacts_def_jobfunctions.ParentJobID <> '1841' 
    LEFT OUTER JOIN 
     newsletterremovelist ON newsletterremovelist.EmailAddress = contacts_link_emails.Email 
WHERE  (newsletterremovelist.EmailAddress IS NULL) 

실망스럽게도, 나는 내 지식의 틈새를 채울 수 없다. 나는 조인을 처음 접했을 때를 제외하고는 시각 도구를 만들어서는 안되기 때문에 연락처, 기관 코드, 추가 코드 및 contacts_link_emails 등 모든 것을 원한다고 생각합니다. 그래서 위에서 (위)에 참여했습니다.

나는 다음 비트에 난처한 상황에 빠진입니다. 내가 그들에 동참하면, 적절한 직업을 가진 사람들을 얻습니다. (<> 1841) -하지만 나는 JobTitle과 JobFunctions에 대한 항목이없는 사람들에게 나가고 싶습니다. 많은 경우에, 이것은 옳지 않습니다. JobTunction 항목이없는 경우 JobTitle "Custodian"을 사용할 수 있지만 INNER JOIN을 사용하면 목록에서 제외됩니다.

그러나 위와 같이 LEFT OUTER JOIN을 사용하여 쿼리를 작성하면 잘못된 JobTitles를 가진 사람들이 많아 질 것입니다. 간단히 말해서 JobTitle이나 JobFunction이 부족한 사람은 내 목록에있을 것입니다. JobFunction이없는 "High Level Executive"일 수 있으며 목록에 올라있을 수 있습니다. 우리는 더 이상 "고위 임원"에게 적합한 서비스를 가지고 있지 않습니다.

는 다음 나는 LEFT OUTER가 newsletterremovelist에 대한 작품을 가입하는 방법을 참조하십시오. 그것은 꽤 빠르 그리고 나는 바로 그것을 한 적이 생각 ...

하지만 난 여전히 갇혔어요. 다행히 누군가 내가 여기서하려고하는 것을보고 올바른 방향으로 나를 조종 할 수 있습니다.

감사합니다,

러셀 SCHUTTE

UPDATE가 다시

는 슬프게도,이 스레드가 완벽한 솔루션 않고, 사망 한 것 같다 -하지만 난 점점 가까이하고 있습니다. 토론을 다시 시작하는 새 스레드를 확인하십시오 : click here

(정답에 도달하지 않은 경우에도 엄청난 양의 작업에 대해 정답을주었습니다).

감사합니다.

러셀 SCHUTTE는

+1

인덱스가 올바른 위치에 있는지 확인하기 위해 EXPLAIN 및 쿼리를 실행 해 보았습니까? –

+0

안녕하세요 잭. 팁 고마워. 일부 데이터베이스 (Oracle/DB2)에서 EXPLAIN을 사용하는 것 같습니다. Microsoft SQL과 관련하여 EXPLAIN에 대해 아무 것도 찾을 수 없습니다. 쿼리 분석기가 있지만 실망스럽게도 MSSQL을 포함하지 않는 로우 엔드 버전이 있습니다. –

답변

6
실제 조인에에서 당신의 WHERE에 쿼리를 이동

. 이것들은 상관 하위 쿼리라고하며 볼드 모트의 작업입니다. 조인 인 경우에는 한 번만 실행되며 쿼리 속도가 빨라집니다.

섹션의 경우 왼쪽 외부 조인을 사용하여 가입 한 열이 NULL인지 확인하십시오.

또한 OR을 가능한 한 WHERE 개의 검색어에 사용하지 마십시오. OR은 반드시 단락 회로 동작이 아닙니다.

SELECT 
    * 
FROM 
    dbo.contacts AS c 
INNER JOIN 
    dbo.contacts_def_jobfunctions AS jf 
    ON c.JobTitle = jf.JobId AND jf.ParentJobID <> '1841' 
INNER JOIN 
    dbo.contacts_link_emails AS e 
    ON c.ContactID = e.ContactID AND jf.JobID = c.JobTitle 
LEFT JOIN 
    dbo.newsletterremovelist AS rl 
    ON e.Email = rl.EmailAddress 
WHERE  
    rl.EmailAddress IS NULL 

이 사용하지 마십시오, 그것은 (SELECT *을 언급하지 않기 위하여), 나는 간단한 예제를 제공하기 위해 contacts_ref_jobfunctions_3에 대한 논리를 무시했습니다 거의 확실히 잘못된 것에 따라 다음과 같이

예입니다. 조인의 (정말) 좋은 설명은

, this visual explanation of joins

+0

나를 용서해라. Khanzor ... 나는 거의 SQL 초보자 다. "실제 조인"은 어떻게 만듭니 까? 나는 Left Outer Join을하는 법을 알고 있다고 생각합니다. –

+0

@ Russell Schutte - 최근 편집을 참조하십시오. WHERE 절 안에 하위 쿼리를 사용하는 대신 위의 "where"를 이동하여 조인으로 설정하십시오. – Khanzor

+0

아, 칸조르. 그건 내게 완전히 새로운 것이다. 나는 생각의 기차를 따라 가려고 노력하고있어 머리가 아프다. 나는 이것을 알아 내려고 노력하면서 스레드를 계속 지켜 볼 것입니다. –

0

은 하위 쿼리가 간단 있도록 할 몇 가지 일반적인 연결을 나타내는 몇 가지보기를 만듭니다. 또한보기가 실행될 때마다 해석 될 필요가 없으므로보기가 조금 더 빠르게 실행됩니다.

+0

안녕 Bnjmn. 나는 이미 그걸 실험 해 봤는데 실제로는별로 도움이되지 못했다. –

0

그것은 사물의 모든 숫자가 될 수보십시오. 내 첫번째 질문은 당신이 색인에 합류하는 열입니까?

더 나은 방법은 SHOWPLAN이며 질문에 붙여 넣으십시오.

+0

나는 SHOWPLAN에 익숙하지 않다. 그러나 작은 검색 결과에 따르면, "SET SHOWPLAN_TEXT ON"을 (SHOWPLAN_TEXT ON을) 새로운 쿼리에 입력하여 MSSQL에서 사용할 수있다. 인용 부호). 결과가 어디서 나왔는지 전혀 알 수 없지만 쿼리를 실행하는 데 필요한 시간이 두 배로 늘어났습니다. 그래서 더 많은 것을 배우기 전에 다시 되돌릴 수 있습니다. :-) 실망스럽게도, 그것은 그것의 속도를 늦추지 않았다 !! 아 !!! –

+0

SHOWPLAN이 꺼진 후 몇 분 후에 다시 가동 된 것으로 보입니다. –

+0

SHOWPLAN은 SQLServer의 쿼리 실행 계획을 보여줍니다. 예를 들어, 쿼리를 실행하는 데 사용중인 인덱스 (사용중인 경우)를 표시합니다. – Todd

관련 문제