这是一个效率/最佳实践问题。希望得到一些性能反馈。非常感谢任何建议。
所以这里有一些我已经设置的背景知识。我正在使用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;
}
所以再一次真正只是寻找关于什么是最有效,最佳实践方式的建议。我真的很感激任何建议或信息。
答案 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)
你可以试试这个:
这将带您从46个查询(对于45个产品)到2个查询,而无需任何其他连接。
如果值得花时间编写代码以在数据更新时重置缓存,那么您还可以使用CodeIgniter的Query Caching来进一步提高性能。
在可扩展性方面,在PHP中做更多工作通常比在MySQL中工作更好。您可以使用负载平衡器和Web服务器轻松扩展PHP。由于并发问题,扩展MySQL并不容易。