简体   繁体   中英

YII SQL Query Optimization

I have a huge list of IDs that i need to query through a table to find if those IDs are available in the table, if yes fetch its model.

Since there are few thousands of IDs this process is really slow as I'm using CActiveRecord::find() mothod

ex. $book = Book::model()->find('book_id=:book_id', array(':book_id'=>$product->book_id));

I even indexed all possible keys, still no improvement. Any suggestions to improve the execution speed?

thanks in advance :)

1) Make a list of book ids

foreach $product in Product-List
    $book_ids[$product->book_id] = $product->book_id;

Now query all Book models ( indexed by book_id )

$books = Book::model()->findAll(array(
    'index' => 'book_id',
    'condition' => 'book_id IN (' . implode(',', $book_ids). ')',
));

Integrate $books in your code, I believe you are looping through all products.

foreach $product in Product-List
    if( isset($books[$product->book_id]) )
        $model = $books[$product->book_id]

2) Another way (I am just assuming you have Product model)

in Product model add a relation to Book

public function relations() {
    .......
    'book'=>array(self::HAS_ONE, 'Book', 'book_id'),
    .......
}

While retrieving your product list, add 'with' => array('book') condition, with any of CActiveDataProvider or CActiveRecord ...

//Example
$productList = Product::model()->findAll(array(
    'with' => array('book'),
));

foreach( $productList as $product ) {
    .......
    if( $product->book != null )
        $model = $product->book;
    ......
}

with either way you can reduce SQL queries.

Better if you use schema caching because Yii fetches schema each time we execute a query. It will improve your query performance.

You can enable schema caching by doing some configuration in config/main.php file.

return array(
    ......
    'components'=>array(
        ......
        'cache'=>array(
            'class'=>'system.caching.CApcCache', // caching type APC cache
        ),

        'db'=>array(
            ...........
            'schemaCachingDuration'=>3600, // life time of schema caching
        ),
    ),
);

One more thing you can fetch specific column of the table that will improve performance also.

You can do it by using CDbCriteria with find method of CActiveRecord .

$criteria = new CDbCriteria;
$criteria->select = 'book_id';
$criteria->condition = 'book_id=:book_id';
$criteria->params = array(':book_id'=>$product->book_id);
$book = Book::model()->find($criteria);

I would suggest you to use any nosql database if you are processing thousands of records if that is suitable.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM