2013-11-22 2 views
3

서브 쿼리를 사용하여 MySQL에서 61 테이블 조인 한도를 줄일 수 있다는 것을 알았습니다. https://stackoverflow.com/a/20134402/2843690MySQL 내에서 61 테이블 JOIN 한계를 해결하려면 서브 쿼리를 중첩하여 처리하십시오.

나는 알아 내기 위해 노력하고있어 어떻게하지만이 질문에 대한 답은 많은에 적용 할 수있을 것 (마 젠토에서 자세한 제품 목록을 가져 일하고 있어요 프로그램에서 쉽게 사용이에 eav가 관련된 상황). 결합 할 필요가있는 테이블은 다음과 같이 보일 :

catalog_product_entity 
+-----------+----------------+ 
| entity_id | entity_type_id | 
+-----------+----------------+ 
|   1 |    4 | 
|   2 |    4 | 
|   3 |    4 | 
|   4 |    4 | 
|   5 |    4 | 
|   6 |    4 | 
|   7 |    4 | 
|   8 |    4 | 
|   9 |    4 | 
+-----------+----------------+ 

catalog_product_entity_int 
+----------+----------------+--------------+-----------+-------+ 
| value_id | entity_type_id | attribute_id | entity_id | value | 
+----------+----------------+--------------+-----------+-------+ 
|  1 |    4 |   2 |   1 | 245 | 
|  2 |    4 |   3 |   1 | 250 | 
|  3 |    4 |   4 |   1 | 254 | 
|  4 |    4 |   2 |   2 | 245 | 
|  5 |    4 |   3 |   2 | 249 | 
|  6 |    4 |   4 |   2 | 253 | 
|  7 |    4 |   2 |   3 | 247 | 
|  8 |    4 |   3 |   3 | 250 | 
|  9 |    4 |   4 |   3 | 254 | 
+----------+----------------+--------------+-----------+-------+ 

eav_attribute 
+--------------+----------------+----------------+--------------+ 
| attribute_id | entity_type_id | attribute_code | backend_type | 
+--------------+----------------+----------------+--------------+ 
|   1 |    4 | name   | varchar  | 
|   2 |    4 | brand   | int   | 
|   3 |    4 | color   | int   | 
|   4 |    4 | size   | int   | 
|   5 |    4 | price   | decimal  | 
|   6 |    4 | cost   | decimal  | 
|   7 |    4 | created_at  | datetime  | 
|   8 |    3 | name   | varchar  | 
|   9 |    3 | description | text   | 
+--------------+----------------+----------------+--------------+ 

eav_attribute_option 
+-----------+--------------+ 
| option_id | attribute_id | 
+-----------+--------------+ 
|  245 |   2 | 
|  246 |   2 | 
|  247 |   2 | 
|  248 |   3 | 
|  249 |   3 | 
|  250 |   3 | 
|  251 |   4 | 
|  252 |   4 | 
|  253 |   4 | 
|  254 |   4 | 
+-----------+--------------+ 

eav_attribute_option_value 
+----------+-----------+-------------------+ 
| value_id | option_id |  value  | 
+----------+-----------+-------------------+ 
|  15 |  245 | Fruit of the Loom | 
|  16 |  246 | Hanes    | 
|  17 |  247 | Jockey   | 
|  18 |  248 | White    | 
|  19 |  249 | Black    | 
|  20 |  250 | Gray    | 
|  21 |  251 | Small    | 
|  22 |  252 | Medium   | 
|  23 |  253 | Large    | 
|  24 |  254 | Extra Large  | 
+----------+-----------+-------------------+ 

나는 이런 식으로 뭔가를 보았다 SQL 쿼리 생성 쓰고 있어요 프로그램 :

SELECT cpe.entity_id 
, brand_int.value as brand_int, brand.value as brand 
, color_int.value as color_int, color.value as color 
, size_int.value as size_int, size.value as size 

FROM catalog_product_entity as cpe 

LEFT JOIN catalog_product_entity_int as brand_int 
ON (cpe.entity_id = brand_int.entity_id 
AND brand_int.attribute_id = 2) 
LEFT JOIN eav_attribute_option as brand_option 
ON (brand_option.attribute_id = 2 
AND brand_int.value = brand_option.option_id) 
LEFT JOIN eav_attribute_option_value as brand 
ON (brand_option.option_id = brand.option_id) 

LEFT JOIN catalog_product_entity_int as color_int 
ON (cpe.entity_id = color_int.entity_id 
AND color_int.attribute_id = 3) 
LEFT JOIN eav_attribute_option as color_option 
ON (color_option.attribute_id = 3 
AND color_int.value = color_option.option_id) 
LEFT JOIN eav_attribute_option_value as color 
ON (color_option.option_id = color.option_id) 

LEFT JOIN catalog_product_entity_int as size_int 
ON (cpe.entity_id = size_int.entity_id 
AND size_int.attribute_id = 4) 
LEFT JOIN eav_attribute_option as size_option 
ON (size_option.attribute_id = 4 
AND size_int.value = size_option.option_id) 
LEFT JOIN eav_attribute_option_value as size 
ON (size_option.option_id = size.option_id) 
; 

코드를 작성하는 것은 상대적으로 쉬웠다을 질의를 생성하고, 질의는 매우 이해하기 쉬웠다. 그러나 실제 데이터로 수행 한 61 테이블 조인 한도를 맞추는 것은 꽤 쉽습니다. 나는 수학에 21 정수형 속성이 한계를 넘을 것이라고 말하고, varchar, text 및 decimal 속성을 추가하기도 전에 그럴 것이라고 생각합니다.

그럼 내가 생각해 낸 해결책은 하위 쿼리를 사용하여 61 개의 테이블 제한을 극복하는 것이 었습니다.

한 가지 방법은 61 조인의 하위 쿼리에서 조인을 그룹화하는 것입니다. 그리고 나서 모든 그룹이 합류 할 것입니다. 나는 sql 쿼리가 어떻게 보이는지 알아낼 수 있다고 생각하지만 쿼리를 생성하는 코드를 작성하는 것은 어렵습니다. 충분한 속성이 있다면 61 테이블 제한을 다시 위반할 수 있다는 (이론적 임에도 불구하고) 문제가 더 있습니다. 즉, 61 개의 테이블로 구성된 62 개의 그룹이있는 경우 MySQL 오류가 발생합니다. 분명히 그룹의 그룹을 61 개 그룹으로 묶어서이 문제를 해결할 수 있습니다.하지만 코드를 작성하고 이해하기가 더욱 어려워집니다.

내가 원하는 해결책은 각 하위 쿼리가 두 테이블 (또는 하나의 테이블과 하나의 하위 쿼리)의 단일 조인을 사용하도록 하위 쿼리 내에서 하위 쿼리를 중첩하는 것입니다. 직관적으로, 이런 종류의 쿼리를 작성하는 것이 코드가 더 쉬워 진 것 같습니다. 불행히도 이러한 쿼리가 어떻게 생겼는지 생각하면 내 머리가 아플 수 있습니다. 그래서 제가 도움이 필요합니다.

그런 MySQL 쿼리는 어떻게 생겼을까요?

+0

"Magento에서 자세한 제품 목록 가져 오기"를 기본 목표로 삼고 있다면 쿼리하려는 속성을 플랫 테이블 인덱스에 포함시킨 다음 'select * from catalog_product_flat_1'을 실행하십시오. 그 중 하나, 또는 기존 Magento 모델을 활용하여 컬렉션을 만들고 표시 할 속성을 선택하십시오. 내 SQL 솔루션은 비효율적 인 접근 방식입니다. – Axel

+0

@Axel catalog_product_flat는 현재의 최신 색인이 필요합니다. 또한 catalog_product_flat에는 내가 원하는 모든 정보가 없습니다. Magento 컬렉션에 관해서는, Magento의 내부 동작에 대해 잘 알고 있지 않습니다. 그리고 지금까지 저는 magento 나 api를 사용하는 것보다 훨씬 빠른 직접적인 mysql 쿼리를 발견했습니다. –

+0

또한 나는 단지 궁금하다. 이 경우 실용적이지 않더라도, 나중에 뭔가 도움이 될 수 있습니다. 적어도 그것은 흥미로울 수 있다고 생각합니다. –

답변

2

EAV 디자인을 통해 너무 많은 속성을 결합하면 조인의 한계를 초과 할 가능성이 있습니다. 그 전에도 너무 많은 조인 비용이 기하 급수적으로 높아지고 기하 급수적으로 높아지기 때문에 실제 조인 제한이 있습니다. 이것이 얼마나 나쁜지는 서버의 용량에 따라 다르지만 61보다 약간 더 낮을 가능성이 있습니다.

따라서 EAV 데이터 모델을 쿼리하여 기존 관계형 모델에 저장된 것처럼 결과를 생성합니다 속성) 문제가 있습니다.

해결 방법 : 속성 당 조인을 사용하지 마십시오. 즉, 순수하게 SQL을 사용하여 엔티티 행당 형식으로 결과를 생성 할 수는 없습니다.

가 나는 젠토 스키마 속속들이 잘 알고 모르겠지만, 이런 식으로 뭔가가 작동 할 수 검색 결과에서 추론 할 수있다 : 여러 속성을 지정할 경우

SELECT cpe.entity_id 
, o.value AS option 
, v.value AS option_value 
FROM catalog_product_entity AS cpe 
INNER JOIN catalog_product_entity_int AS i 
    ON cpe.entity_id = i.entity_id AND i.attribute_id IN (2,3,4) 
INNER JOIN eav_attribute_option AS o 
    ON i.value = o.option_id AND i.attribute_id = o.attribute_id 
INNER JOIN eav_attribute_option_value AS v 
    ON v.option_id = o.option_id; 

IN(2,3,4,...) 조건입니다. 더 많은 속성을 얻기 위해 더 많은 조인을 추가 할 필요가 없습니다. 단순히 열이 아닌 행으로 반환됩니다.

즉,이 결과 집합의 모든 행을 가져와 단일 객체의 필드에 매핑하는 응용 프로그램 코드를 작성해야합니다.

@Axel의 의견에서 Magento는 결과 집합을 소비하고이를 객체에 매핑하는 도우미 함수를 제공하는 것처럼 들립니다.

+0

정확히 내가 원하는 것은 아니지만 실제로 구현하는 것이 훨씬 쉬울 것입니다. 감사. 기록을 위해 아마존 RDS를 사용하고 있으며 마이크로 인스턴스조차도 61 테이블 조인 (또는 심지어 61 테이블의 하위 쿼리와 조인 된 61 테이블 하위 쿼리)에 대해서는 문제가 거의 없습니다. Magento 나 그 API를 통해 유사한 쿼리를하면 어색하게 느려지므로 상대적이라고 생각합니다. 또한 Magento는 MySQL 로그를 살펴 보았을 때보다 현명한 접근 방식을 취하지 않았으며 실제로 복잡한 JOIN을 사용했습니다 (플랫 인덱스 테이블 사용은 물론). –

+0

이 기본 문제는 조인해야하는 테이블의 값이 아니라 ID 만 반환한다는 것입니다. – gshauger