【问题标题】:YII SQL Query OptimizationYII SQL 查询优化
【发布时间】:2012-10-09 02:20:58
【问题描述】:

我有一个巨大的 ID 列表,我需要通过一个表查询这些 ID 是否在表中可用,如果是,则获取其模型。

由于有几千个 ID,这个过程真的很慢,因为我正在使用 CActiveRecord::find() 方法

例如。 $book = Book::model()->find('book_id=:book_id', array(':book_id'=>$product->book_id));

我什至索引了所有可能的键,但仍然没有改进。 有什么提高执行速度的建议吗?

提前感谢:)

【问题讨论】:

  • 我不明白,它的 $product->book_id 是一个 id 数组?
  • 为什么不使用IN 子句和->findAll?? ...在一次拍摄中,您将获得所有记录并将它们设为哈希(按 id)并使用它。
  • @Asgaroth :对不起,它循环遍历数组,并且在每次迭代时 $product->book_id 都会保存一个新值
  • @SuVeRa : 你能解释一下如何做吗?
  • 正如 onkarjanwa 所建议的,如果您正在处理数千条记录并且您不一定需要关系功能,那么最好使用 mongodb 之类的东西。

标签: mysql yii


【解决方案1】:

1) 制作图书ID列表

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

现在查询所有 Book 模型(由 book_id 索引)

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

在您的代码中集成$books,我相信您正在循环所有产品。

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

2)另一种方式(我只是假设你有产品模型)

在 Product 模型中添加与 Book 的关系

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

在检索您的产品列表时,使用 CActiveDataProvider 或 CActiveRecord 中的任何一个添加 'with' => array('book') 条件...

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

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

无论哪种方式,您都可以减少 SQL 查询。

【讨论】:

    【解决方案2】:

    如果您使用模式缓存会更好,因为 Yii 每次执行查询时都会获取模式。它将提高您的查询性能。

    您可以通过在config/main.php 文件中进行一些配置来启用架构缓存。

    return array(
        ......
        'components'=>array(
            ......
            'cache'=>array(
                'class'=>'system.caching.CApcCache', // caching type APC cache
            ),
    
            'db'=>array(
                ...........
                'schemaCachingDuration'=>3600, // life time of schema caching
            ),
        ),
    );
    

    您还可以获取表的特定列,这也将提高性能。

    您可以通过使用CDbCriteriaCActiveRecord 的查找方法来做到这一点。

    $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);
    

    如果您正在处理数千条记录,如果合适的话,我建议您使用任何nosql 数据库。

    【讨论】:

    • 我试过了,但没有太大的改善。还有其他建议吗?
    • 即使你是否使用'select'子句执行,还是希望它返回一个ActiveDataProvider?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-01-10
    • 2014-02-04
    • 2014-11-16
    • 2011-06-22
    • 2015-08-10
    相关资源
    最近更新 更多