2013-08-14 4 views
0

나는 완전히 mysql에 익숙하며 아래의 mysql 쿼리를 실행하려고 시도했지만 엄청나게 천천히 달리고있는 것으로 보인다. 표는 약 100MB이고 약 2 백만 행이 들어 있습니다.매우 느린 쿼리

Create TEMPORARY table temp_table as 
(
SELECT 
    pcur.RECORD_ID, 
    pcur.Price, 
    (pcur.Price - plast.Price) as 'Price_Difference', 
     CASE 
     when plast.Price between 0 and 0.25 then ((pcur.Price - plast.Price)/0.001) 
     when plast.Price between 0.2501 and 0.5 then ((pcur.Price - plast.Price)/0.005) 
     when plast.Price between 0.5001 and 10 then ((pcur.Price - plast.Price)/0.01) 
     when plast.Price between 10.0001 and 20 then ((pcur.Price - plast.Price)/0.02) 
     when plast.Price between 20.0001 and 100 then ((pcur.Price - plast.Price)/0.05) 
     when plast.Price between 100.0001 and 200 then ((pcur.Price - plast.Price)/0.1) 
     when plast.Price between 200.0001 and 500 then ((pcur.Price - plast.Price)/0.2) 
     when plast.Price between 500.0001 and 1000 then ((pcur.Price - plast.Price)/0.5) 
     when plast.Price between 1000.0001 and 2000 then ((pcur.Price - plast.Price)/1) 
     when plast.Price between 2000.0001 and 5000 then ((pcur.Price - plast.Price)/2) 
     when plast.Price between 5000.0001 and 9995 then ((pcur.Price - plast.Price)/5) 
    END AS Price_Diff_Ticks 
FROM 
    /* First aliased table is the current record */ 
    00005 pcur 
    /* Second aliased table is the previous one, whose id is one behind */ 
    LEFT JOIN 00005 plast ON (pcur.Record_ID = plast.Record_ID + 1) 

) 
; 

테이블의 인덱스 보고서.

"Table" "Non_unique" "Key_name" "Seq_in_index" "Column_name" "Collation" "Cardinality" "Sub_part" "Packed" "Null" "Index_type" "Comment" "Index_comment" 
============================================================================================ 
"00005" "0" "PRIMARY" "1" "RECORD_ID" "A" "2275579" "" "" "" "BTREE" "" "" 

무엇이 잘못 되었나요? 또는 내가 느리게 만들 수 없었던 것은 무엇입니까?

+0

길이가 길어질 수 있습니다. 어쩌면 테이블을 만든 다음 데이터를 따로 삽입 해보십시오. 나는 모른다. –

+0

인덱스가 클러스터되지 않은 경우 클러스터 된 상태로 만들거나 포함 된 열로 "Price"를 추가 할 수 있습니다. 그렇지 않으면, 조회는 비용이 많이 드는 색인 스캔을 반복해야합니다. – McGarnagle

+0

여기에 문제가 될만한 것이 없습니다. 인덱스가 있으므로 조인이 나쁘지 않습니다. 비 클러스터형이라 할지라도 2 백만 건의 조회 만 있습니다. 이 사건은 매우 간단합니다. 그래서 나는 다른 문제를 의심 할 것입니다 :이 테이블이 사용 중입니까? 어쩌면 당신의 프로세스는 테이블을 잠그고있는 다른 사람들에 의해 굶어 죽을지도 모릅니다. IO는 어떤가? 어쩌면이 테이블을 만들 때 공간을 할당하거나 소스를 읽을 가능성이 적습니다. –

답변

2

내가 상상할 수있는 한 가지는 필드 중 하나에 산술 연산이 있기 때문에 MySQL이 인덱스를 사용하지 않거나 비효율적으로 사용한다는 것입니다. 그것은 추측입니다.

변수를 사용하여 쿼리를 작성할 수 있습니다. 내가 선호하는 접근 방식은 아니지만이 경우 작동 할 수 있습니다.

Create TEMPORARY table temp_table as 
SELECT pcur.RECORD_ID, pcur.Price, (pcur.Price - @prevPrice) as 'Price_Difference', 
     CASE 
     when @prevPrice between 0 and 0.25 then ((pcur.Price - @prevPrice)/0.001) 
     when @prevPrice between 0.2501 and 0.5 then ((pcur.Price - @prevPrice)/0.005) 
     when @prevPrice between 0.5001 and 10 then ((pcur.Price - @prevPrice)/0.01) 
     when @prevPrice between 10.0001 and 20 then ((pcur.Price - @prevPrice)/0.02) 
     when @prevPrice between 20.0001 and 100 then ((pcur.Price - @prevPrice)/0.05) 
     when @prevPrice between 100.0001 and 200 then ((pcur.Price - @prevPrice)/0.1) 
     when @prevPrice between 200.0001 and 500 then ((pcur.Price - @prevPrice)/0.2) 
     when @prevPrice between 500.0001 and 1000 then ((pcur.Price - @prevPrice)/0.5) 
     when @prevPrice between 1000.0001 and 2000 then ((pcur.Price - @prevPrice)/1) 
     when @prevPrice between 2000.0001 and 5000 then ((pcur.Price - @prevPrice)/2) 
     when @prevPrice between 5000.0001 and 9995 then ((pcur.Price - @prevPrice)/5) 
    END AS Price_Diff_Ticks, 
    @prevPrice = pcur.Price 
FROM /* First aliased table is the current record */ 
    00005 pcur cross join 
    (select @prevprice := NULL) const 
order by Record_Id; 
+0

덕분에 놀랍도록 훨씬 더 빨라졌습니다. 멈추기로 결정한 시점에서 20 시간 10 시간이 아닌 다른 20 시간이었습니다. 단 하나의 문제가 있지만, 가격은 십진법 (7,3)입니다. 가격 차이가 이중으로 보이는 끝에 반올림 오류가 발생합니다. 예 : 1.200 - 1.100 = 0.09999999999999432입니다. 재미있는 산술 연산이나 타이핑이 있습니까? – user2676706

+0

@ user2676706 . . 'declare @ prevprice'를'price'와 같은 타입으로 지정하기 만하면됩니다. 기본값은 float입니다. –

+0

예, 맞는 말이군요. 이 문맥에서 변수를 어떻게 선언 할 수 있습니까? 아마도'Begin declare @prevprice decimal (7,3);을 사용해야 할 것입니다. 끝 '? – user2676706