数据库 结构 , Eav 模型 , 太慢 的 搜索 查询

Posted

技术标签:

【中文标题】数据库 结构 , Eav 模型 , 太慢 的 搜索 查询【英文标题】:Database Structure , Eav model , too slow search queries 【发布时间】:2015-06-17 11:51:25 【问题描述】:

我正在创建一个汽车销售网站。我有一个car_properties 表来存储我的汽车属性,例如 ABS、气候、导航、警报等。

我正在为 car properties 表使用 EAV 模型,所以我的表看起来像:

id , name , value , car_id

我的汽车主桌:car_sale 桌:

id, price , brand , mode , year 

但是对于 1 辆车,我在 car_properties 表中有大约 25-30 行。想想 300 辆汽车,car_properties 表中大约有 9000 行。

我的主页上有一个详细的搜索选项。

search filters : Brand , Model , Location , Year-to-Year , Price-to-price , condition , tranmission and so on 

但是当我添加 2 或 3 辆车时,它的运行速度太慢了!我的搜索查询如下:

        $query = CarSale::
          where('car_model_id', '=', $model_id)
        ->join("car_properties as cp1", "cp1.car_for_sale_id", "=", "car_for_sale.id")
        ->join("car_properties as cp2 ", "cp2.car_for_sale_id", "=", "cp1.car_for_sale_id")
        ->join("car_properties as cp3 ", "cp3.car_for_sale_id", "=", "cp2.car_for_sale_id")
        ->join("car_properties as cp4 ", "cp4.car_for_sale_id", "=", "cp3.car_for_sale_id")
        ->join("car_properties as cp5 ", "cp5.car_for_sale_id", "=", "cp4.car_for_sale_id")
        ->join("car_properties as cp6 ", "cp6.car_for_sale_id", "=", "cp5.car_for_sale_id")
        ->groupBy('car_for_sale.id')
        ->select('car_for_sale.*' );


    if($year1!='' and $year2!='')
        $query->where('year', '>=' , $year1 )->where('year', '<=' , $year2);
    
    if($price1!='' and $price2!='')
        $query->where('price', '>=' , $price1 )->where('price', '<=' , $price2);
    
    if($location!='')
        $query->where("cp1.name",'=',"location")
              ->where("cp1.value",'like',"%$location%");
    
    if($condition!='')
        $query->where("cp2.name",'=',"condition")
              ->where("cp2.value",'like',"%$condition%");
    
    if($transmition!='')
        $query->where("cp3.name",'=',"gearbox")
              ->where("cp3.value",'like',"%$transmition%");
    
    if($wheel!='')
        $query->where("cp4.name",'=',"steering_wheel")
              ->where("cp4.value",'like',"%$wheel%");
    
    if($fuel!='')
        $query->where("cp5.name",'=',"fuel_type")
              ->where("cp5.value",'like',"%$fuel%");
    
    if($imported!='')
        $query->where("cp6.name",'=',"customs")
              ->where("cp6.value",'=',$imported);
    

    $results = $query->get(); //finally get the result

    return view('frontend.category')->with('results', $results );

这里有什么问题!结构、搜索查询或逻辑? (我正在使用 php laravel 5,mysql-InnoDB) 感谢您的帮助!

【问题讨论】:

这就是 EAV 被视为反模式的原因之一。使用您应该使用的数据库:使用真实列。 删除带有“like”关键字的条件,看看是否遇到同样的性能问题。 hımm ,我应该用什么来代替 like= ? 如果您不需要 EAV,请不要使用它。如果您确实需要 EAV,请记住,使用 EAV 可能无法实现关系设计的大部分事情 - 例如搜索。即使可以写,它们也会非常缓慢。 【参考方案1】:

不要将eav 模型用于您的searchable 字段。如果你有很多 fields 并且需要像我一样 filter 他们,尝试使用像 ElasticSearch 这样的搜索引擎来达到这个目的。

【讨论】:

【参考方案2】:

EAV 很烂。

确定一些通常会被搜索且选择性好的列。将它们放在主表的列中。确定几个复合索引。将其余字段放入 JSON 中的一个额外列中。使用 MySQL 过滤具有列的属性,然后使用 PHP 完成 JSON 数据的过滤。

More discussion in my EAV blog.

【讨论】:

以上是关于数据库 结构 , Eav 模型 , 太慢 的 搜索 查询的主要内容,如果未能解决你的问题,请参考以下文章

关系模型与EAV

EAV模型

雄辩的 ORM 和 EAV

实体-属性-值 (EAV) 的替代方案?

保管 EAV 的最佳实践

Magento学习手记(第一天)