2012-03-21 3 views
2

나는 느린 쿼리를 최적화하려고하는데 다음과 같이 일관되게 실행됩니다 (8 초 이상 지속).논리를 유지하면서 JOIN에 서브 쿼리

SELECT entryID, entryID AS iE, 0 AS eE, 'clarus1' AS locationID, dateStamp, amount AS income, NULL AS expense, reconciled, leaseID AS vendorID, incomeID AS expenseID 
FROM structu_income.iLedger 
WHERE (dateStamp BETWEEN '2009-04-16' AND '2012-02-29') AND incomeID IS NOT NULL 
    AND (
     leaseID IN (
      SELECT lease.leaseID FROM structu_assets.lease WHERE lease.unitID IN (
       SELECT unit.unitID FROM structu_assets.unit WHERE unit.locationID = 'clarus1' 
      ) 
     ) 
     OR locationID IN (SELECT locationID FROM structu_assets.deed WHERE ownerID = 'clarus') 
    ) 

다음은 EXPLAIN입니다 :

enter image description here

내 생각 JOIN를 사용하도록 하위 쿼리를 리팩토링하는 것이 었습니다. 그러나 논리를 유지하는 것은 OR 나를 날려 버리고있다.

또한 중첩 된 하위 쿼리는 피할 수없는 것처럼 보입니다. 별도의 쿼리로 unitID을 미리 지정하지 않았다면.

저는 원래 개발자가 아닙니다. 하지만 기존의 코드베이스 나 스키마를 수정하지 않고도 더 뛰어난 성능을 제공 할 책임이 있습니다. 그래서 느린 쿼리를 선택하려고합니다.

제쳐두고 크로스 데이터베이스 쿼리는 성능에 문제가 있습니까?

+0

주로 HEAP (in-memory) 엔진을 사용하고 디스크 기반 시스템 (예 : myisam/innodb)을 사용하는 테이블을 쿼리 할 때 히트가 발생할 수 있지만 엔진 효율성 차이와 몇 가지 추가 사용 권한/보안 확인, 눈에 띄는 피해는 없어야합니다. –

+0

@Marc B, 관련된 모든 테이블은 MyISAM입니다. 내 * 제쳐두고 * 또는 일반적으로 질문에 대한 귀하의 요점이었다. –

+0

그냥 제쳐두고. –

답변

1

귀하의 dateStamp 열에 색인을 추가하십시오.

사용 : 대신

dateStamp > '2009-04-16' AND dateStamp < '2012-02-29' 

는 :

dateStamp BETWEEN '2009-04-16' AND '2012-02-29' 

것이 더 효율적입니다.

마지막으로 하위 쿼리 대신 PHP로 루프를 작성할 수 있습니다.

+0

이미 있습니다. 나는 그것이 그것을 사용하지 않고 있다는 것을 발견했다. 게다가, 당신은 논리적으로 동등하지 않은 (자정) 예제입니다. –

1

이 대답이 a)이고, b)이 더 빠르다는 것이 흥미로울 것입니다. 이 시도 :

SELECT 
    il.entryID, 
    il.entryID AS iE, 
    0 AS eE, 
    'clarus1' AS locationID, 
    il.dateStamp, 
    il.amount AS income, 
    NULL AS expense, 
    il.reconciled, 
    il.leaseID AS vendorID, 
    il.incomeID AS expenseID 
FROM 
    structu_income.iLedger il 
    INNER JOIN structu_assets.lease l ON il.leaseID = l.leaseID 
    INNER JOIN structu_assets.unit u ON l.unitID = u.unitID AND u.locationID = 'clarus1' 
WHERE 
    il.dateStamp BETWEEN '2009-04-16' AND '2012-02-29' 
    AND il.incomeID IS NOT NULL 
UNION 
SELECT 
    il.entryID, 
    il.entryID AS iE, 
    0 AS eE, 
    'clarus1' AS locationID, 
    il.dateStamp, 
    il.amount AS income, 
    NULL AS expense, 
    il.reconciled, 
    il.leaseID AS vendorID, 
    il.incomeID AS expenseID 
FROM 
    structu_income.iLedger il 
    INNER JOIN structu_assets.deed d ON il.locationID = d.locationID AND d.ownerID = 'clarus' 
WHERE 
    il.dateStamp BETWEEN '2009-04-16' AND '2012-02-29' 
    AND il.incomeID IS NOT NULL 

첫 번째 SELECT 쿼리는 OR 조건의 전반을 담당하고, 두 번째 SELECT 쿼리는 하반기에 대한 결과에 추가합니다. 그리고 UNION으로 중복 행을 가져 오지 않아야하므로 동일한 결과를 얻어야합니다.

+0

작동합니다. 벤치마킹 할 때 시간 감소는 없습니다. +1 철저한 대답을하지만. –

+0

적어도 조인을 사용하여 하위 서브 쿼리 ('OR'조건의 첫 번째 부분)를 제거 할 수 있어야합니다. '선택 lease.leaseID FROM structu_assets.lease INNER JOIN structu_assets.unit ON lease.unitID = unit.unitID WHERE unit.locationID = 'clarus1 ''. – Travesty3