Codeigniter数据库调用效率

时间:2011-11-11 17:30:24

标签: mysql performance codeigniter

这是一个效率/最佳实践问题。希望得到一些性能反馈。非常感谢任何建议。

所以这里有一些我已经设置的背景知识。我正在使用codeigniter,基本设置与任何其他产品关系非常相似。基本表是:品牌,产品,类别。在这些表格的顶部,需要安装表,营销材料和颜色。

我创建了一些关系表:   Brands_Products   Products_Colors   Products_Images   Products_Sheets

我还有一个Categories_Relationships表,其中包含与类别的所有关系。安装表等可以有自己的类别,但我不想为每种类型定义不同的类别关系表,因为我认为这不会是非常可扩展的。

在前端,我按品牌和类别进行排序。

我认为现在涵盖效率部分的背景。我想我的问题主要与天气有关,最好是使用连接或单独调用以返回每个项目的各个部分(颜色,图像等)

我目前编码的是工作,并且排序很好,但我认为我可以提高性能,因为它需要一些时间来返回查询。现在它返回约45项。这是我的第一个功能,它抓住了所有产品及其信息。

首先选择所有产品并加入其品牌信息。然后循环遍历结果我设置基本信息,但对于类别图像和安装,我使用的函数返回每个受尊重的项目。

public function all()
    {
        $q = $this->db
                    ->select('*')
                    ->from('Products')
                    ->join('Brands_Products', 'Brands_Products.product_id = Products.id')
                    ->join('Brands', 'Brands.id = Brands_Products.brand_id')
                    ->get();

        foreach($q->result() as $row)
        {
            // Set Regular Data
            $data['Id'] = $row->product_id;
            $data['Name'] = $row->product_name;
            $data['Description'] = $row->description;
            $data['Brand'] = $row->brand_name;
            $data['Category'] = $this->categories($row->product_id);
            $data['Product_Images'] = $this->product_images($row->product_id);
            $data['Product_Installs'] = $this->product_installs($row->product_id);
            $data['Slug'] = $row->slug;


            // Set new item in return object with created data
            $r[] = (object)$data;
        }


        return $r;
    }

以下是用于获取各个部件的功能之一的示例。

private function product_installs($id)
    {
        // Select Install Images 
        $install_images = $this->db
                  ->select('*')
                  ->where('product_id', $id)
                  ->from('Products_Installs')
                  ->join('Files', 'Files.id = Products_Installs.file_id')
                  ->get();

        // Add categories to category object
        foreach($install_images->result() as $pImage)
        {
            $data[] = array(
                        'id' => $pImage->file_id, 
                        'src' => $pImage->src,
                        'title' => $pImage->title,
                        'alt' => $pImage->alt
                        );
        }

        // Make sure data exists
        if(!isset($data))
        {
            $data = array();
        }

        return $data;
    } 

所以再一次真正只是寻找关于什么是最有效,最佳实践方式的建议。我真的很感激任何建议或信息。

2 个答案:

答案 0 :(得分:0)

我认为你的方法是正确的。只有几个选项:1)首先加载产品列表,然后循环,并为每个产品行加载所需的数据。 2)首先在所有表上创建一个大连接,然后循环(可能是大量)笛卡尔积。第二个可能会变得难以解析。例如,如果您有产品A和产品B,而产品A有安装1,安装2,安装3,产品B有安装1,安装2,那么你的结果是 产品A安装1 产品A安装2 产品A安装3 产品B安装1 产品B安装2

现在,将您的图片和类别添加到联接中,它可能会变得很大。

我不确定你的桌子大小是多少但是返回45行不应该花很长时间。确保(并且您可能已经这样做)显而易见的事情是,product_id在所有表以及brands_products表和其他表中都被编入索引。否则,您将进行表扫描。

接下来的问题是您如何在屏幕上显示数据。所以你得到了所有的产品。当您获得产品列表时,是否需要加载类别,图像和安装?如果您只是在屏幕上列出产品,则可能需要等待加载该数据,直到用户选择他们正在查看的产品为止。

在旁注中,您将数组转换为对象

的任何原因
$r[] = (object)$data;

此外,在第二个功能中,您只需添加

即可
$data = array();
在foreach之前,而不是

// Make sure data exists
if(!isset($data))
{
    $data = array();
} 

答案 1 :(得分:0)

你可以试试这个:

  1. 查询所有产品
  2. 获取步骤1中的所有产品ID
  3. 查询所有具有步骤2中的产品ID的安装映像,按产品ID
  4. 排序
  5. 遍历第1步中的产品,并添加第3步的结果
  6. 这将带您从46个查询(对于45个产品)到2个查询,而无需任何其他连接。

    如果值得花时间编写代码以在数据更新时重置缓存,那么您还可以使用CodeIgniter的Query Caching来进一步提高性能。

    在可扩展性方面,在PHP中做更多工作通常比在MySQL中工作更好。您可以使用负载平衡器和Web服务器轻松扩展PHP。由于并发问题,扩展MySQL并不容易。