Magento 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');

และผลลัพธ์ของฉันมีดังต่อไปนี้บนเซิร์ฟเวอร์ 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 (หลังจากโหลดหลังจากลบ) หรือล้างดัชนี / แคช

คำถาม

ดังนั้นคำถามของฉันคือ: มีเหตุผลwalk('delete')หรือไม่ที่ทีมหลักของวีโอไอพีไม่ได้ใช้วิธีการหรือเหตุการณ์ที่ดีกว่าdelete()วิธีการเก็บรวบรวมแทนที่จะโหลดผลิตภัณฑ์ในลูป

เป้าหมายหลักคือการตระหนักถึงประเด็นสำคัญดังกล่าวในกรณีที่มีการพัฒนาโมดูล: มีกรณีใดบ้างที่ไม่มีวิธีการwalk/ การรวบรวมdelete()?

แก้ไข: เหตุผลไม่แน่นอนเพราะcatalog_controller_product_deleteเหตุการณ์ที่ถูกส่งเป็นรหัสเดียวกันสามารถพบได้ในหลายสถานที่ (ตรวจสอบmassDeleteวิธีการ) ในแกนกลางวีโอไอพี ฉันใช้ตัวอย่างผลิตภัณฑ์เพื่อเน้นประสิทธิภาพเนื่องจากเป็นเอนทิตีที่ใหญ่ที่สุด


3
ฉันเดาว่ามันเป็นเพราะเหตุการณ์ แต่ฉันเห็นด้วยกับคุณมันเป็นสไตล์ที่ไม่ดีโดยเฉพาะอย่างยิ่งการใช้getSingleton()เป็นมาตรวัดประสิทธิภาพแทนการใช้คอลเลกชันที่ชัดเจน โอ้และเป็นไปได้ที่จะเรียกเหตุการณ์ด้วยคอลเลกชันเช่นกันไม่ใช่ด้วยwalk()ทางลัด
Fabian Schmengler

1
@fschmengler ใช่ฉันคิดเกี่ยวกับเหตุการณ์ด้วย แต่เมื่อฉันบอกว่าในการแก้ไขของฉันมันเกิดขึ้นในหลาย ๆ ที่ที่ไม่มีการส่งกิจกรรม
Raphael ที่ Digital Pianism

3
ไม่น่าแปลกใจ delete()สร้างคิวรี DELETE แทนการโหลดคอลเล็กชันและลบแต่ละผลิตภัณฑ์ ด้วยเหตุการณ์นั้นคุณจะคลายเหตุการณ์อย่างแท้จริง
Fabian Schmengler

5
@fschmengler การลบคอลเลกชันยังทำการลบสำหรับแต่ละไอเท็ม แต่จะข้ามการล้างแคชและเรียกใช้เหตุการณ์วีโอไอพีและตัวทำดัชนี นั่นคือสิ่งที่แตกต่างต้องมาจาก
Vinai

2
@Vinai คุณพูดถูก ความคิดที่ต้องการในด้านของฉัน
เฟเบียน Schmengler

คำตอบ:


4

ดังนั้นฉันจึงทำการทดสอบประสิทธิภาพเพิ่มการเรียกการบันทึกเพื่อตรวจสอบเวลาที่ใช้และการใช้หน่วยความจำสำหรับการลบผลิตภัณฑ์ 100 รายการ

หมายเหตุด้านข้าง แต่คุณควรพิจารณาใช้ Varien Profiler สำหรับสิ่งนี้!

รหัสที่กำหนดเองของฉันเร็วขึ้น 2 วินาทีและใช้น้อยกว่า 0.4MB

แม้ว่าฉันจะไม่สงสัยเลยว่าการเปลี่ยนแปลงของคุณจะปรับปรุงประสิทธิภาพ แต่ก็มีประโยชน์ที่จะให้ผลลัพธ์ "ก่อน" เพื่อเปรียบเทียบการปรับปรุง

มีเหตุผลใดที่ทีมหลักของ Magento ไม่ได้ใช้walk('delete')แทนการโหลดผลิตภัณฑ์ในลูป

เรารู้จากคำถามอื่น ๆ ในฟอรัมนี้ดังต่อไปนี้:

  • โค้ดเบสของ Magento ได้รับการพัฒนาและพัฒนามาเป็นเวลาหลายปี
  • มีนักพัฒนาจำนวนมากทำงานอยู่
  • กระบวนการเวิร์กโฟลว์การพัฒนาหลักของวีโอไอพีได้รับการปรับปรุงอย่างมากตลอดเวลาที่พวกเขาทำงานบนแพลตฟอร์มทันกับแนวทางปฏิบัติที่ดีที่สุดและเทคนิคที่ทันสมัยจนถึงจุดที่ Magento 2 ในขณะนี้แสดงการออกแบบแอปพลิเคชันที่ทันสมัย

ดังนั้นฉันขอแนะนำว่าตัวอย่างที่คุณพบอาจเป็นหนึ่งในอัญมณีที่ซ่อนอยู่ในรหัสที่เขียนมานานแล้วและ / หรือโดยนักพัฒนาที่มีประสบการณ์น้อยกว่า เช่นเดียวกับแกนประมวลผลหลัก (และรหัสชุมชน!) จะได้รับการทดสอบในชุดข้อมูลขนาดเล็กและไม่ได้ทดสอบการต่อสู้ดังนั้นประสิทธิภาพอาจไม่ได้รับการตรวจสอบอย่างใกล้ชิด

การปรับปรุงของคุณมีประโยชน์และสอดคล้องกับแนวปฏิบัติที่ดีที่สุดมากกว่ารหัสต้นฉบับหรือไม่ ใช่. คุณในฐานะนักพัฒนาชุมชนวีโอไอพี [1.x] แต่ไม่มีความสามารถที่จะมีส่วนร่วมในการปรับปรุงที่แนะนำเช่นเดียวกับที่คุณทำกับวีโอไอพี 2 ดังนั้นข้อเสนอแนะของฉันจะนำไปใช้ในโมดูลท้องถิ่นหากคุณต้องการใช้งาน หรือเพิกเฉยถ้ามันไม่ส่งผลกระทบต่อคุณ แต่คุณสังเกตเห็นมันในขณะที่ทำการวิจัย

เป็นการอัปเดตสำหรับการแก้ไขคำถามของคุณฉันแน่ใจว่าคุณทราบว่าวิธีการเดินใน Varien_Data_Collection ยอมรับการโทรกลับโดยพลการดังนั้นคุณจะสามารถใช้งานได้ฟรีสำหรับทุกสิ่งที่คุณต้องการ สำหรับการส่งเหตุการณ์ในตัวอย่างดั้งเดิมคุณสามารถทำได้ด้วยฟังก์ชั่นการเดินรวมถึงการลบ

เหตุผลเดียวที่ฉันนึกภาพได้ว่าการโหลดผลิตภัณฑ์ก่อนที่จะลบอาจเป็นเพราะการใช้งานอาจเป็นเพราะผู้สังเกตการณ์ที่แนบมากับเหตุการณ์นั้นอาจต้องใช้ชุดข้อมูลแบบเต็มไม่สามารถใช้งานได้โดยไม่ต้องโหลดผลิตภัณฑ์ก่อน หากเป็นกรณีนี้มันจะอธิบายว่าทำไมพวกเขาจึงใช้ซิงเกิลตันมากกว่าแบบจำลองเพื่อลดค่าใช้จ่ายของวัตถุอย่างน้อยที่สุด


ขอบคุณฉันได้เพิ่มผลลัพธ์ก่อนและหลังในโพสต์ ดังนั้นคุณคิดว่าไม่มีเหตุผลใดที่นอกเหนือจากความจริงที่ว่ามันเป็นรหัสเก่า?
Raphael ที่ Digital Pianism

2
นั่นจะเป็นการเดาของฉันใช่ การโหลดผลิตภัณฑ์ก่อนที่จะลบมันจะไม่เกิดประโยชน์อะไรนอกจากการโหลดเหตุการณ์โหลดซึ่งไม่เกี่ยวข้องกับการลบ โดยปกติคุณโหลดผลิตภัณฑ์เพื่อรับชุดข้อมูลแบบเต็มซึ่งอาจจำเป็นสำหรับหนึ่งในผู้สังเกตการณ์ที่แนบกับเหตุการณ์ - หากเป็นกรณีนี้มันจะอธิบายว่าทำไมพวกเขาถึงใช้ซิงเกิลตันแทนที่จะเป็นแบบจำลอง
Robbie Averill

1
ดูการแก้ไขของฉันด้วยการทดสอบเพิ่มเติมผลลัพธ์ยิ่งขึ้น
ราฟาเอลที่ Digital Pianism

0

ความคิดของฉันคือพวกเขากำลังทำเพื่อจุดไฟcatalog_controller_product_deleteเหตุการณ์ที่ Mage_Tag ใช้

catalog_product_delete_beforeหรือcatalog_product_delete_afterจะหมายความว่าไม่จำเป็นแม้ว่าฉันจะคิด สงสัยว่าเหตุการณ์นี้จะใช้สำหรับการบันทึกการดำเนินการของผู้ดูแลระบบด้วยหรือไม่


คิดอย่างนั้นเหมือนกัน แต่นั่นก็ไม่ใช่เหตุผลที่มันเกิดขึ้นกับการmassDelete()กระทำของCustomerController.php
Raphael ที่ Digital Pianism

ดูการแก้ไขของฉันด้วยการทดสอบเพิ่มเติมผลลัพธ์ยิ่งขึ้น
ราฟาเอลที่ 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.