দক্ষ সংগ্রহ কলিং, ফিল্টারিং এবং লোড হচ্ছে


15

এই মুহুর্তে আমি প্রচুর সংগ্রহগুলি পুনরায় ব্যবহার করছি যা পূর্বাভাসের লুপের মধ্যে বাসা বাঁধে। এই জিনিসগুলি কয়েক স্তরের উপরে সরানো কি সম্ভব? বর্তমানে আমি বার বার ৫১ কে + সত্তা সংকলন পুনরায় লোড করতে বাধ্য করেছি যা জিনিসগুলি দুর্দান্তভাবে ধীর করে দেয়। বিশেষত ক্যাটিনভেন্টরি সংগ্রহ।

<?php
class Codespace_Module_Helper_Item extends other_one{

function functionOne($collection){
    ...
    $data = $collection->getData();
    foreach($data as $item){
        $this->_functionTwo($item);
    }
    ...
}

function _functionTwo($item){
    $model = Mage::getModel('catalog/product');
    $id = $model->getIdBySku($item['sku']);
    $inventoryStatus = Mage::getResourceSingleton('catalog/product')->getAttributeRawValue($id, 'product_inventory_status', 1);
    $invStatus = $model->getResource()->getAttribute('product_inventory_status')->getSource()->getOptionText($inventoryStatus);
    if ($invStatus && $id) {
        if ($invStatus !== 'Z') {
            $stockItem = Mage::getModel('cataloginventory/stock_item');
            $stockItem->setData(array());
            $stockItem->loadByProduct($id);
            if ($stockItem->getQty() != $item['quantity']) {
                $stockItem->setQty(item['quantity']);
                $stockItem->save();
                $this->functionThree($item['sku']);
            }
        }
    }
}

function functionThree($sku){
    $collectionOfKits = Mage::getModel('kitinventory/kitinventory')->getCollection()->addFieldToFilter('related_sku',$sku);
    if($collectionOfKits->getSize()){
        foreach($collectionOfKits as $kit){
            $kitSku = $kit->getSku();
            $kitCollection = Mage::getModel('kitinventory/kitinventory')->getCollection()->addFieldToFilter('kit_sku',$kitSku)->setOrder('related_sku','ASC');
            ...
            foreach($kitCollection as $component){
                $componentSkus[] = $component->getRelatedSku();
                $componentRequiredQuantity[] = $component->getRequiredQuantity();
            }
            $componentProductCollection = Mage::getModel('catalog/product')->getCollection();
            $componentProductCollection->joinField('qty',
                'cataloginventory/stock_item',
                'qty',
                'product_id=entity_id',
                '{{table}}.stock_id=1',
                'left');
            $componentProductCollection->addAttributeToFilter('sku', array('in' => $componentSkus));
            foreach($componentProductCollection as $component){
                $quantity = $component->getQty();
                ...
            }
            $kitId= Mage::getModel('catalog/product')->getIdBySku($kitSku)
            $kitStockItem = Mage::getModel('cataloginventory/stock_item')->loadByProduct($kitId);
            $this->functionFour($kitStockItem,$kitSku,$amountOfKitsPossible);
        }
    }
}

function functionFour($kitStockItem,$kitSku,$amountOfKitsPossible){
    ...
    $kitStockItem->setQty($quantity);
    $kitStockItem->save();
    ...
}

সম্পাদনা: এটি বর্তমান কার্যকারিতা যা আমি সামনে এনেছি, আমি এখনও মনে করি এই সংগ্রহগুলি পরিচালনা করার আরও ভাল উপায় আছে।


কোন ধরণের সংগ্রহ পাস হয় functionOne($collection)? এটি কোন আকারে আইটেমের আকার / গণনা হবে? এসকিউ'র জন্য এটি কী লুপ করা দরকার?
7ochem

@ 7 ওচেম এটি নতুন তালিকা ডেটা থেকে তৈরি একটি কাস্টম সংগ্রহ যা আমরা আমাদের ইনভেস্টরি ম্যানেজমেন্ট সিস্টেম থেকে পাই from এটিতে আইটেমের নাম, হাতে আইটেমের পরিমাণ এবং আইটেমের স্কু রয়েছে। এটিতে সম্ভাব্যভাবে 60k + উপাদান থাকতে পারে।
easymoden00b

উত্তর:


9

আপনি কয়েকটি বিষয় নিয়ে কাজ করতে পারেন;

  • রেফারেন্স দ্বারা পাস না, সুতরাং অতিরিক্ত মেমরি ব্যবহার করে আপনি বস্তুগুলি পাস করতে পারেন, তবে অ্যারেগুলি ডিফল্টরূপে রেফারেন্স দিয়ে পাস করা যায় না। অথবা &মত পরামিতি ঘোষণায় একটি যুক্ত করুনfunction hello(array &$world)
  • অবৈধ চেক, যদি কিছু না থাকে তবে তাৎক্ষণিকভাবে ফিরে আসে। এমন কিছু খুঁজে পাওয়ার চেষ্টা করবেন না যা সেখানে নেই
  • পাঠযোগ্যতা কখনও কখনও কঠিন হতে পারে
    • কিছু দস্তাবেজ যুক্ত করুন (যাতে আপনি এটি কয়েক দিন, সন্ন্যাসীদের, বছরগুলিতে দেখতে পান তবে বুঝতে পারবেন)
    • স্মার্ট ifস্টেটমেন্ট কম ইন্ডেন্টেশন পেতে
  • ফাংশনগুলির একটিমাত্র উদ্দেশ্য থাকতে হবে, আপডেট স্টক বা আপডেট সম্পর্কিত হওয়া উচিত, উভয়ই নয়, তাই এমনকি এমনকি আরও ছোট ফাংশনে কিছু ফাংশনও কাটতে পারে। আপনার মনে মনে এই জাতীয় যুক্তি তৈরি করার চেষ্টা করুন এবং সেখান থেকে পুনরায় কাজ করুন।
  • কিছু বিষয়বস্তুর জন্য অন্তর্নিহিত ডেটা সাফ করার জন্য একবার ->cleanModelCache()->clearInstance()থেকে একবার দেখুন Mage_Core_Model_Model_Abstract, জিনিসগুলিকে গতি বাড়িয়ে দিতে পারে।
  • ইতিমধ্যে বলা হয়েছে যে অন্যান্য সমস্ত জিনিস মোটা।

আপনার বর্তমান কোডটিতে কিছু ইনলাইন প্রস্তাবনা সহ আপনার কোডের একটি আপডেট সংস্করণ যুক্ত করা হয়েছে, আমি কিছুটা যেতে পারি, তবে এটি বর্তমানে এতে আরও যুক্ত করবে না।

ফাংশন 1: উদ্দেশ্যটি সংগ্রহে চলছে

    /**
     * Walk collection
     * 
     * @param Mage_Core_Model_Resource_Db_Collection_Abstract $collection
     * @return void
     */
    public function functionOne($collection)
    {
        // ...

        // Walk collection, create references instead of passing array data
        foreach ($collection as $item) {

            // Update stock for product
            if (!$this->_functionTwo($item)) {
                // Not updated, continue next
                continue;
            }

            // Update related products
            $this->_functionThree($item); // Use same object again, no extra memory is used
        }

        // ...
    }

কাজ 2: উদ্দেশ্য পরিবর্তিত হলে স্টক আপডেট করা হয় is

    /**
     * Update stock item if changed, returns true if updated
     * 
     * @param Mage_Core_Model_Model_Abstract $item
     * @return bool
     */
    function _functionTwo($item)
    {
        $model = Mage::getModel('catalog/product');
        /** @var $model Mage_Catalog_Model_Product */

        $id = $model->getIdBySku($item->getData('sku'));

        if (!$id) {
            // no id found, so stop looking nothing up
            return false;
        }

        // Get option value for store 1
        $inventoryStatus = $model->getResource()
                ->getAttributeRawValue($id, 'product_inventory_status', 1);

        if (!$inventoryStatus) {
            // No need for another lookup in db, because the status isn't set
            return false;
        }

        $invStatus = $model->getResource()
                ->getAttribute('product_inventory_status')
                ->setStoreId(0) // Get admin value
                ->getSource()
                ->getOptionText($inventoryStatus);

        if (!$invStatus) {
            // No need for another lookup in db, because the status has no text
            return false;
        }

        if ($invStatus === 'Z') {
            // Inventory status to not change something
            return false;
        }

        $stockItem = Mage::getModel('cataloginventory/stock_item');
        /** @var $stockItem Mage_CatalogInventory_Model_Stock_Item */

        // $stockItem->setData(array()); // unneeded piece of code
        $stockItem->loadByProduct($id);

        if ($stockItem->getQty() == $item->getData('quantity')) {
            // Valid stock
            return false;
        }

        // Update stock
        $stockItem->setQty($item->getData('quantity'));
        $stockItem->save();

        // End function and call function three separately, does something else
        return true;
    }

ফাংশন 3: সম্পর্কিত স্টক আইটেমগুলি আপডেট করার উদ্দেশ্য

    /**
     * Update related stock items, return false if no related items are found
     * 
     * @param Mage_Core_Model_Model_Abstract $item
     * @return bool
     */
    function functionThree($item)
    {

        $collectionOfKits = Mage::getModel('kitinventory/kitinventory')
                ->getCollection()
                ->addFieldToFilter('related_sku', $item->getData('sku')); // Check if your indexes are set on these columns

        if (!$collectionOfKits->getSize()) {
            // Nothing found to relate to
            return false;
        }

        $connection = Mage::getSingleton('core/resource')
                ->getConnection('core_write');

        // Walk kits
        foreach ($collectionOfKits as $kit) {

            // getData is slightly faster then getSku(unless you've implemented it in your model)
            // getSku -> __call('getSku') -> get -> lowercase('sku') -> getData('sku') | note, Magento has some internal caching in this 
            $kitSku = $kit->getData('sku');

            $kitCollection = Mage::getModel('kitinventory/kitinventory')
                    ->getCollection()
                    ->addFieldToFilter('kit_sku', $kitSku)
                    ->setOrder('related_sku', 'ASC');

            // Use just a fetchAll to create a fast db query
            $select = $kitCollection->getSelect();

            $select->reset(Zend_Db_Select::COLUMNS)
                    ->distinct()
                    ->columns('related_sku')
                    ->columns('required_quantity');

            // Fetch component sku
            $componentSkus = $connection->fetchAll($select, 0);

            // Fetch required quantity
            $componentRequiredQuantity = $connection->fetchCol($select, 1);

            // ...

            $componentProductCollection = Mage::getModel('catalog/product')
                    ->getCollection()
                    ->joinField('qty',
                    'cataloginventory/stock_item',
                    'qty',
                    'product_id = entity_id',
                    '{{table}}.stock_id = 1',
                    'left');
            $componentProductCollection->addAttributeToFilter('sku', array('in' => $componentSkus));

            // Next line will invoke a load on the product collection
            foreach ($componentProductCollection as $component) {
                $quantity = $component->getQty();

                // ...

            }
            // You could choose to do a fetchAll here instead to get just the data you need
            $connection = $componentProductCollection->getConnection();

            foreach ($connection->fetchAll($componentProductCollection->getSelect()) as $row) {
                // Will have a array here
                $quantity = $row['quantity'];

                // ... -- do not not which funky magic happens here
            }


            $kitId = Mage::getModel('catalog/product')
                    ->getIdBySku($kitSku);
            if (!$kitId) {
                // No id
                continue;
            }

            // You could also take a look if you can sum the stock and do a single update instead
            $kitStockItem = Mage::getModel('cataloginventory/stock_item')
                    ->loadByProduct($kitId);
            $this->functionFour($kitStockItem, $kitSku, $amountOfKitsPossible);

            // Or something like this, update single field
            $connection->update($kitStockItem->getResource()->getMainTable(), array('qty' => $quantity), 'item_id = ' . $kitStockItem->getId());
        }

        return true;
    }

ফাংশন 4: কিছু ভাগ্যবান (বা দুর্ভাগ্যজনক) অনুমান করা উচিত ছিল, আপাতত এটি একটি অকেজো ফাংশন, ফাংশন 3-তে যুক্ত করা যেতে পারে।

    /**
     * Save stock item if changed and something else, rather not say ;-)
     * 
     * @param Mage_Catalog_Inventory_Model_Stock_Item $kitStockItem
     * @param string $kitSku
     * @param int $amountOfKitsPossible Guessed it
     */
    function functionFour($kitStockItem, $kitSku, $amountOfKitsPossible)
    {

        // ...

        // Do not know the rest of the code, so I wouldn't know which I could optimize here
        // If it isn't to serious, you could look at a single query and not hitting extra functions

        // Check if changed
        if ($quantity !=$kitStockItem->getData('qty')) {
            $kitStockItem->setQty($quantity);
            $kitStockItem->save();
        }        

        // ...

    }
}

তুমি আসল পুরুষ. আমি তুলনামূলকভাবে নিশ্চিত যে এটি কাজ করবে, এবং যদি এটি প্রক্রিয়াজাতকরণের সময় একটি পৃথক উন্নতি দেখায়, সংগ্রহগুলি হেরফেরের জন্য আমার যেতে যাওয়া রেফারেন্স হতে পারে!
easymoden00b

কয়েকটি ছোট ত্রুটি, তবে এটি আমার নিজের থেকে আরও ভাল নির্মিত।
easymoden00b

5

আমি এটি একটি মন্তব্য হিসাবে যুক্ত করতে চেয়েছিলাম তবে আমার এখনও যথেষ্ট প্রতিনিধি নেই। কীভাবে ম্যাজেন্টো কোর গ্রিডগুলি এখানে ক্যাটালগ / পণ্য সংগ্রহের পণ্যটিতে যোগ দেয় তা দেখুন: https://github.com/OpenMage/magento-mirror/blob/magento-1.9/app/code/core/Mage/Adminhtml /Block/Catalog/Product/Grid.php#L65

আপনি কিটিটি পেতে টেবিলে যোগ দিলে আপনাকে এটিকে একটি লুপে কল করতে হবে না: Mage::getModel('cataloginventory/stock_item')->loadByProduct($product)->getQty();

$productCollection = Mage::getModel('catalog/product')->getCollection();
$productCollection->joinField('qty',
    'cataloginventory/stock_item',
    'qty',
    'product_id=entity_id',
    '{{table}}.stock_id=1',
    'left');
$productCollection->addAttributeToFilter('sku',array('in' => $relatedSkus));
foreach($productCollection as $product){
    $quantity = $product->getQty();
    ...// now you have your qty without having to load the product model.
}

অন্য বিকল্পটি হ'ল আপনি এই সিস্টেমের নিবিড় প্রক্রিয়ার ফলাফলগুলি ক্যাশে করতে পারেন কিনা তা দেখুন। ফলাফল সংরক্ষণের জন্য আপনি দ্বিতীয় ডাটাবেস টেবিল তৈরি করতে পারেন এবং এটি ম্যাজেন্টো সূচকের মতো রিফ্রেশ করতে পারেন।


আমি কীভাবে এই তথ্যের উপরের কোডের সাথে একইভাবে কল করতে পারি তা ভাগ করে নেওয়ার যত্ন নিন? এছাড়াও, যদি আমি পণ্য সংগ্রহ উত্পন্ন করি এবং তাদেরকে একটি শ্রেণি ভেরিয়েবলের জন্য বরাদ্দ করি তবে আমি কি এই কোডটি পুরো কোডটিতে কল করতে সক্ষম হব? ফিল্টারিং (কোড হিসাবে দেখানো হয়েছে) ক্লাস ভেরিয়েবলকে প্রভাবিত করবে বা আমি যদি এই ফিল্টার সংগ্রহটি অন্য ভেরিয়েবলের কাছে অর্পণ করি তবে তা অপরিবর্তিত থাকবে?
easymoden00b

আমি কীভাবে মাঠে যোগ দিতে পারি তার একটি উদাহরণ যোগ করেছি, তবে এটি কেবল একটি ছোট্ট অপটিমাইজেশন। হ্যাঁ: আপনি ফলাফলগুলি বর্গ ভেরিয়েবল হিসাবে সংরক্ষণ করতে এবং অন্য কোথাও কল করতে পারেন। তবে: আমি মনে করি আপনি প্রতিবার ফিল্টারিং পরিবর্তন করতে চাইলে আপনাকে একটি নতুন মডেল ইনস্ট্যান্ট করতে হবে (উদ্দেশ্যটি হারাতে পারে
এরিক সিস্ট্র্যান্ড

আপনাকে ধন্যবাদ, আমি যেমন ভীত হয়েছি তেমনটি উপস্থিত হয়। অপ্টিমাইজেশনের এই উদাহরণের জন্য ধন্যবাদ। অন্য কেউ আপনি ভাবতে পারেন? উপরের কোড উদাহরণে আমি প্রতিটি সংগ্রহের ব্যবহারগুলি কিছুটা ব্যাখ্যা করব।
easymoden00b

3

আপনাকে মডেলটি বার বার পুনরায় লোড করার দরকার নেই, Mage::getModel()আপনার উত্সের মডেলগুলি মেমোরিতে প্রতিবার পুনরায় পুনরায় পুনরুদ্ধারিত হচ্ছে এবং সেই লুপগুলিতে আপনি শেষ পর্যন্ত ফাঁস / ফুরিয়ে চলেছেন তা জানার জন্য কীভাবে আপনার উত্সের মডেলগুলি সেটআপ হয় তা জেনে রাখা যথেষ্ট a মেমরির কারণে ডিস্কের অদলবদল ঘটে।

তাদের সমস্তকে শাসনের জন্য একটি সংগ্রহ। কেবলমাত্র একটি সংগ্রহের উল্লেখ করার জন্য ফাংশনগুলিকে রিফ্যাক্টরিং। এটি স্ট্যান্ডার্ড এসকিউএল এবং পদ্ধতিগত প্রোগ্রামিংয়ের সাথে একই। এসকিউএল থেকে আপনার প্রয়োজনীয় সমস্ত ডেটা আপনি কীভাবে একবারে পেতে পারেন, সম্ভবত দুবার এবং তারপরে পর্যাপ্ত মেমরির পাশাপাশি প্রদর্শন / ম্যানিপুলেশনের জন্য লুপিংয়ের জন্য ডেটা উল্লেখ করার জন্য আপনার সংগ্রহ এবং সংস্থান সংক্রান্ত মডেলগুলি তদন্ত করতে আরও কিছুটা সময় নিন। ক্যাশে বনাম অনেকের মধ্যে একটি ফলাফল সংরক্ষণ করাও সহজ, এটি মাইএসকিউএলের অন্তর্নির্মিত ক্যাচিং প্রক্রিয়াগুলির ক্ষেত্রেও একই ঘটনা, কারণ প্রায়শই বড় হওয়া অনুরোধগুলি একই ডিস্কের অদলবদলের কারণ হতে পারে।

I / O সংরক্ষণ করুন

একই পদ্ধতির প্রয়োগের জন্য বিনাইয়ের একটি ভাল উদাহরণ রয়েছে:

তথ্যসূত্র :

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.