2013-08-03 3 views
-1

## MySQL 서버 5.5, 데이터베이스 엔진 MYISAM, 테이블 fact_transaction가 date_key, time_key, unit_cost_price, time_key을 제외 fact_stockout_sales에 대한 unit_retail_price (조합 키)와 같은에 색인이 생성됩니다. ##선택 쿼리 최적화 거대한 데이터

Query plan

Query plan

쿼리

SELECT 
    t.Level, t.Name, t.KeyValue, 
    ROUND((SUM(t.Gross)/SUM(t.Revenue))*100, 2) AS Value, 
    ROUND((SUM(t.adjustedGross)/SUM(t.adjustedRevenue))*100, 2) AS adjustedValue, 
    t.dataType AS dataType 
FROM 
    (SELECT "item" AS Level, ds.product_name AS Name, ds.product_id AS KeyValue, 
     SUM(ft.gross_profit) AS Gross, 
     SUM(ft.selling_amount) AS Revenue, 
     SUM(ft.adjusted_gross_profit) AS adjustedGross, 
     SUM(ft.adjusted_selling_amount) AS adjustedRevenue, 
     "%" AS dataType 
    FROM fact_transaction AS ft 
    JOIN dim_sku AS ds ON ft.sku_key = ds.sku_key 
    WHERE ft.date_key BETWEEN 20080215 AND 20130107 
     AND ft.time_key BETWEEN 100 AND 235900 
     AND ft.unit_cost_price BETWEEN 0 AND 1333 
     AND ft.unit_retail_price BETWEEN 0 AND 16500 
     AND ft.store_key IN ("1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16") 
     AND ds.product_id IN (1312009,1312007,... Huge List say 30000) 
     AND ds.category IN ("Male","Female","Unisex") 
     AND ft.day_of_week IN ("1","2","3","4","5","6","7") 
     AND ds.collection_name IN ("Base","SS12","AW12") 
    GROUP BY ds.product_id       
    UNION 
    SELECT "item" AS Level, ds.product_name AS Name, ds.product_id AS KeyValue, 
     SUM(ft.gross_profit) AS Gross, 
     SUM(ft.selling_amount) AS Revenue, 
     SUM(ft.adjusted_gross_profit) AS adjustedGross, 
     SUM(ft.adjusted_selling_amount) AS adjustedRevenue, 
     "%" AS dataType 
    FROM fact_stockout_sales AS ft 
    JOIN dim_sku AS ds ON ft.sku_key = ds.sku_key 
    WHERE ft.date_key BETWEEN 20080215 AND 20130107 
     AND ft.unit_cost_price BETWEEN 0 AND 1333 
     AND ft.unit_retail_price BETWEEN 0 AND 16500 
     AND ft.store_key IN ("1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16") 
     AND ds.product_id IN (1312009,1312007,.. Huge List say 30000) 
     AND ds.category IN ("Male","Female","Unisex") 
     AND ft.day_of_week IN ("1","2","3","4","5","6","7") 
     AND ds.collection_name IN ("Base","SS12","AW12") 
     GROUP BY ds.product_id) AS t 
GROUP BY t.KeyValue 
+0

왜 UNION을 사용하여 두 개의 ** 동일 ** 쿼리를 결합합니까? 이것은 느려야합니다. 동일한 질의가 두 번 실행되면 UNION은 두 개의 동일한 결과 집합을 결합하여 중복을 제거합니다. – krokodilko

+0

@kordirko : 그들은 동일하지 않습니다. 그들은 두 개의 다른 테이블에서 선택하고, 두 번째는 WHERE 절에서 ft.time_key를 생략합니다. –

+0

Righ, 그들은 동일하지 않습니다. 하지만 두 하위 쿼리 모두 동일한 테이블'dim_sku'에 대한 조인을 포함하므로'dim_sk' 스캔을 피하기 위해 "join factorization"을 사용하여이 쿼리를 변환하려고 시도 할 수 있습니다.이 링크는이 변환이 어떻게 작동하는지 설명합니다. http://docs.oracle. com/cd/E16655_01/server.121/e15858/tgsql_transform.htm # BABHGGEG – krokodilko

답변

0
  1. 실행 시간을 측정하십시오.

  2. UNION 연산자의 각 쿼리에 대해 실행할 시간을 측정하십시오.

  3. WHERE 절에 사용 된 모든 열을 인덱싱합니다.

  4. 가장 중요한 선택 열을 먼저 WHERE 절에두고 다중 열 인덱스 효과를 테스트하십시오.

  5. 쓸모없는 테스트를 자릅니다. (ft.day_of_week은 WHERE 절에서 제거 할 수 있습니다.)

  6. 데이터 유형을 다시 고려하십시오. 주일과 가게 열쇠가 일 실제로 문자열입니까?

  7. 한 번에 5 년 동안 데이터를 선택하라는 결정을 재고하십시오.

  8. 제품 ID 번호를 임시 테이블로 옮기고 결합하십시오.

+0

을 사용하는 법 1.Date, time, costPrice, retailPrice가 가장 많이 사용되는 colmns이며 그 이유는 바로 다음에 나타납니다. 2.day_of_week, store_id, product_id의 데이터 유형은 정수입니다. 3.Combined Indx가 우세한 열 (데이터, 시간, costPrice, retailPrice)에 대해 수행 중입니다. 4. 붙여 넣기 한 쿼리는 product_id를 제외한 정확한 쿼리입니다. – Itachi

+0

* Predominant *와 * selective *는 영어로 같은 것을 의미하지 않습니다. WHERE 절에서 사용되는 * selective * 열에 복합 인덱스를 작성하려고합니다. 정확한 쿼리에 대한 내 의견은 저의 실수였습니다 - 불일치하는 괄호가 있다고 생각했습니다. –