마 젠토 1 : 엔티티 삭제를위한 성능 최적화


10

현재 성능과 관련하여 몇 가지 모듈을 개선하려고합니다.

일부 사용자는 콜렉션 에서 메소드사용법을 알고있을 수 있으며 이는 제품을 직접 루핑하는 것을 피하는 데 매우 유용합니다.walk()

또한 @Vinai 덕분에 수집 delete()방법을 사용할 수도 있습니다 .

그러나 Magento 1 기본 파일이 항상 이러한 방법을 사용하여 삭제하는 것은 아닙니다.

내가 본 최악의 코드 중 하나는 삭제 전에 제품이 루프에로드 되는 massDelete()방법입니다 .app/code/core/Mage/Adminhtml/controllers/Catalog/ProductController.php

foreach ($productIds as $productId) {
    $product = Mage::getSingleton('catalog/product')->load($productId);
    Mage::dispatchEvent('catalog_controller_product_delete', array('product' => $product));
    $product->delete();
}

그래서 몇 가지 성능 테스트를 수행하고 소요 시간과 100 제품 삭제에 대한 메모리 사용량을 확인하기 위해 로깅 호출을 추가했습니다.

시험 1 : walk방법

위에 붙여 넣은 원래 코드를이 코드로 바꿨습니다.

$collection = Mage::getResourceModel('catalog/product_collection')
                        ->addAttributeToSelect('entity_id')
                        ->addIdFilter($productIds)
                        ->walk('delete');

그리고 내 결과는 내 crappy dev 서버에서 다음과 같습니다 (평균 10 테스트 기준).

  • 원본 코드 : 19.97 초, 15.84MB 사용
  • 맞춤 코드 : 17.12 초, 15.45MB 사용

따라서 100 개의 제품을 삭제하는 경우 사용자 지정 코드가 3 초 빨라지고 0.4MB가 줄어 듭니다.

테스트 2 : 수집 delete()방법 사용

원래 코드를 다음 코드로 바꿨습니다.

$collection = Mage::getResourceModel('catalog/product_collection')
                        ->addAttributeToSelect('entity_id')
                        ->addIdFilter($productIds)
                        ->delete();

그리고 마음이 불어 여기 결과는 다음과 같습니다

  • 원본 코드 : 19.97 초, 15.84MB 사용
  • 맞춤 코드 : 1.24 초, 6.34MB 사용

따라서 100 개의 제품을 삭제하면 사용자 지정 코드가 18 초 빨라지고 9MB가 줄어 듭니다.

주석에서 언급 했듯이이 방법은 Magento 이벤트 (로드 후, 삭제 후) 또는 인덱스 / 캐시 플러시를 트리거하지 않는 것처럼 보입니다.

질문

그래서 내 질문은 : Magento 핵심 팀이 루프에 제품을로드하는 대신 walk('delete')수집 delete()방법을 더 잘 사용하지 않는 이유가 있습니까?

주요 목표는 모듈 개발의 경우 이러한 핵심 사항을 인식하는 것입니다 . walk/ 수집 delete()방법을 사용할 수없는 특별한 경우가 있습니까?

편집 : 이유는 Magento 코어 catalog_controller_product_delete의 여러 곳에서 동일한 코드를 찾을 수 있기 때문에 이벤트가 전달 되기 때문이 아닙니다 massDelete. 제품의 예를 사용하여 일반적으로 가장 큰 엔티티이므로 성능을 강조했습니다.


3
이벤트 때문인 것 같아 그러나 나는 당신에게 동의합니다, 그것은 나쁜 스타일, 특히 getSingleton()명백한 컬렉션 사용 대신에 성능 측정으로 사용됩니다. 아 그리고 walk()바로 가기가 아닌 컬렉션으로 이벤트를 트리거 할 수 있습니다 .
Fabian Schmengler 2016 년

1
@fschmengler 예, 이벤트에 대해서도 생각했지만 편집에서 말했듯이 이벤트가 전달되지 않는 많은 곳에서 발생합니다.
디지털 피아니즘의 Raphael

3
놀랍지 않습니다. delete()컬렉션을로드하고 각 제품을 삭제하는 대신 DELETE 쿼리를 만듭니다. 그것으로 당신은 정말로 사건을 풀어 놓을 것입니다.
Fabian Schmengler 2016 년

5
@fschmengler 컬렉션 삭제는 각 개별 항목에 대한 삭제도 수행하지만 캐시를 지우고 일부 마 젠토 및 인덱서 이벤트를 트리거하지는 않습니다. 그것이 차이점에서 비롯된 것입니다.
Vinai 2016 년

2
@Vinai 당신이 맞아요. 내 곁에 희망찬 생각
Fabian Schmengler

답변:


4

그래서 몇 가지 성능 테스트를 수행하고 소요 시간과 100 제품 삭제에 대한 메모리 사용량을 확인하기 위해 로깅 호출을 추가했습니다.

참고 사항이지만 Varien Profiler를 사용하는 것이 좋습니다!

내 사용자 정의 코드는 2 초 빠르며 0.4MB를 덜 사용합니다.

변경 사항이 성능을 향상시킬 것이라는 점은 의심의 여지가 없지만 개선 사항을 비교하기 위해 "이전"결과를 제공하는 것이 좋습니다.

Magento 코어 팀이 walk('delete')루프에 제품을로드 하는 대신 대신 사용하지 않은 이유가 있습니까 (우리 모두가 매우 나쁜 습관이라고 알고 있습니다)?

글쎄, 우리는이 포럼의 다른 질문에서 다음을 알고 있습니다.

  • Magento 코드베이스는 수년에 걸쳐 개발 및 발전해 왔습니다
  • 많은 개발자들이 작업하고 있습니다.
  • Magento 핵심 개발 워크 플로우 프로세스는 플랫폼에서 작업 한 시간이 지남에 따라 크게 개선되었으며, Magento 2는 현재 여러 가지 주요 현대적인 응용 프로그램 설계 사례를 보여주는 최신 모범 사례와 기술을 따라 잡았습니다.

그래서 당신이 찾은 예제는 아마도 오래 전에 작성된 경험이 있거나 경험이 부족한 개발자가 작성한 코드에 숨겨져있는 많은 보석 중 하나 일 것입니다. 많은 핵심 코드 (및 커뮤니티 코드!)와 마찬가지로 소규모 데이터 세트에서 테스트되었지만 전투 테스트되지 않았으므로 성능을 면밀히 모니터링하지 못할 수 있습니다.

개선이 유익하고 원래 코드보다 모범 사례에 더 가깝습니까? 예. 그러나 커뮤니티 Magento [1.x] 개발자는 Magento 2와 마찬가지로 제안 된 개선 사항을 제공 할 능력이 없으므로 상점 중 하나에서 성능을 요구하는 경우 로컬 모듈에서이를 구현하는 것이 좋습니다. 영향을 미치지 않지만 조사하는 동안 눈치 채 셨으면 무시하십시오.

질문 편집에 대한 업데이트로 Varien_Data_Collection의 walk 메소드는 임의의 콜백을 허용하므로 원하는대로 자유롭게 사용할 수 있습니다. 원래 예제에서 이벤트를 전달하려면 walk 함수와 delete 함수를 사용하여 이벤트를 전달할 수 있습니다.

제품을 삭제하기 전에 제품을로드하는 것이 유용하다고 생각할 수있는 유일한 이유는 해당 이벤트에 연결된 관찰자가 제품을 먼저로드하지 않고 사용할 수없는 전체 데이터 세트가 필요할 수 있기 때문일 수 있습니다. 이 경우 객체 오버 헤드를 최소화하기 위해 모델이 아닌 싱글 톤을 사용하는 이유를 설명합니다.


감사합니다. 전과 후 결과를 게시물에 추가했습니다. 그래서 당신은 그것이 오래된 코드라는 사실 외에는 특별한 이유가 없다고 생각합니까?
디지털 피아니즘의 Raphael

2
그건 내 추측 이겠지 삭제하기 전에 제품을로드하면 삭제와 관련이없는로드 이벤트를 발생시키는 것 외에 다른 이점은 없습니다. 일반적으로 이벤트에 첨부 된 관찰자 중 하나에 필요할 수있는 전체 데이터 세트를 얻기 위해 제품을로드합니다.이 경우 모델 대신 싱글 톤을 사용하는 이유를 설명합니다.
로비 애 버릴

1
더 많은 테스트를 통해 편집 한 결과를보고 결과가 더 미쳐집니다.
Raphael at Digital Pianism

0

내 생각은 그들이 catalog_controller_product_deleteMage_Tag가 사용 하는 이벤트를 시작하기 위해하고 있다는 것입니다.

catalog_product_delete_before또는 catalog_product_delete_after내가 생각하지만 이것이 불필요하다는 것을 의미합니다. 이 특정 이벤트가 관리자 작업 로깅에도 사용되는지 궁금합니다.


너무 그것에 대해 생각하지만, 그것은 또한 위해 발생으로 그 확실히 이유 아닙니다 massDelete()의 행동CustomerController.php
디지털 Pianism에서 라파엘

더 많은 테스트를 통해 편집 한 결과를보고 결과가 더 미쳐집니다.
Raphael at Digital Pianism

0

대량 삭제는 단일 (완전로드) 제품을 삭제하는 것처럼 작동해야한다고 생각합니다.

대한 $collection->delete()대답이 이미 주어집니다. 당신이 방아쇠를하지 않으면 deleter_before, delete_after나는 아마도 몇 가지 확장을 깰 수있는 핵심에 사용되는 일부 관측을 우회 할 것이다.

$collection->walk('delete')작동하지만 제품 데이터가 완전하지 않다는 단점이 있습니다. 또한 추가 관찰 데이터 (예 : 재고 항목 개체)에 의존하는 경우 사용자 지정 관찰자가 중단 될 수 있습니다.

제품에 재고 데이터를 추가 ->addAttributeToSelect('entity_id')하기 위해 변경 ->addAttributeToSelect('*')하고 추가 ->setFlag('require_stock_items', true)하면 "루프 삭제"보다 성능이 좋지 않습니다.

나쁜 스타일처럼 보이지만 대량 삭제 작업에 모두 적합하다고 생각합니다.

내가 사용 walk()하고 delete()도 사용자 정의 모델,하지만 난 거기에 더 관찰자 없거나 것을 알고 entity_id충분하다. 간단히 말해서 walk()코어에서만 사용되는 모든 이벤트에서 작동합니다. 왜냐하면 오직을 사용하기 때문 $product->getId()이지만 타사 관찰자는 알 수 없습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.