[原创]Magento customer eav属性静态化

      今天,给大家分享加速eav模型实体数据查询的方法,截止到v1.4.2,其余的order, product, 都已经做了“进化”了,为什么order可以脱离eav,customer又迟迟不做提速呢,个人觉得是因为需求的不确定性,毕竟每个公司的会员属性都不一定,order字段值相对固定一些。

在collection 加载多个eav的属性之后,echo  (string) $collection->getSelect(); 很多时候你会看到一串长达半屏的sql 查询语句,相信很多magento的开发者都会这样的体会,这样的查询,怎么可能效率高呢?实际上这就是eav带来的一个重大的弊端。使用EAV模型,理想的状态下,我们的表数据会变得更加“紧凑”,但是在生产环节中的实验证明了并不是这样,数据并不是很饱和,反而增加多表之间关联查询的开销。而且,当会员量在100万时,按照每个会员有10个varchar属性时,customer_entity_varchar表往往已经接近1000万,这样两个/多个巨型的表进行join查询,而且还有int等其他类型的表查询,对于普通的架构其效率是一个难题,而往往实际应用中varchar的表增长是最快的,很多初步接触magento的朋友都滥用了动态属性,或者因为不敢改动核心表而盲目增加动态属性。那如果已经加了怎么办?下面介绍如何将动态属性转换以及其相应的数据处理,如何将动态映射到 eav属性类型表中的数据 集中到 customer_entity 表来,以提高查询速度的方法。在进行修改前,请把断开新的数据写入,并把数据库备份好,以便失败后的恢复。

1,为customer_entity 表增加已有/新增的属性,可以做为一个模块的 数据库升级脚本

  alter table `{$this->getTable('customer_entity')}`
     add column `rank_id` smallint default 1 comment '会员级别',
     add column `gender` tinyint(1) comment '性别',
#     add column `taxvat` varchar(100),
#     add column `default_shipping` int(10),
#     add column `default_billing` int(10),
     add column `password_hash` varchar(100),
     add column `confirmation` varchar(100),
     add column `dob` datetime comment '生日',
#     add column `last_birthday` datetime comment '上次生日购物',
#     add column `prefix` varchar(10),
#     add column `suffix` varchar(10),
#     add column `middlename` varchar(10),
     add column `firstname` varchar(10),
     add column `lastname` varchar(50),
     add column `mobile` varchar(15) comment '手机号码',
     add column `created_in` varchar(20) comment '商店标识';

其中#注释的属性,我保留在映射表中,因为这些字段仅有部分会员拥有,这样就减少collection查询所耗费的内存。记住加速的原则是把必要字段都加到entity表中来,减少其他类型表的数据量,另外一方面,把不是必要的字段保留在映射表中,以尽量减少collection的规模。在实际应用中,还需要对customer_form_attribute,customer_eav_attribute表进行修改,才能达到较为理想的效果,这里不做延伸。

2,对customer动态属性的数据进行转移,插入到 customer_entity 表新字段中,运行下面action

    public function exchangeAction()
    {
        set_time_limit(1800);   //语句运行的时间较长,设置超时时间
        $mysqlServerName="localhost";
        $mysqlDatabase="";
        $mysqlUsername="";
        $mysqlPassword="";
        $conn=@mysql_connect($mysqlServerName, $mysqlUsername, $mysqlPassword);
        mysql_query("set names 'utf8' ");
        
$start= 20000;  //这里定义开始点跟结束点,数值为 customer的 entity_id;
$stop= 50000;
        
        for($i=$start; $i<=$stop; $i++){
            $model= Mage::getModel('customer/customer')->load($i);
            if($model->getId()) $tmp= $model->getData();
            else continue;
            $strSql="update `bio_customer_entity` set ";
    if(isset($tmp['rank_id'])) $strSql .= '`rank_id`="'. $tmp['rank_id']. '",';
    if(isset($tmp['gender'])) $strSql .= '`gender`="'. $tmp['gender']. '",';
    //if(isset($tmp['taxvat'])) $strSql .= '`taxvat`="'. $tmp['taxvat']. '",';
    //if(isset($tmp['default_shipping'])) $strSql .= '`default_shipping`="'. $tmp['default_shipping']. '",';
    //if(isset($tmp['default_billing'])) $strSql .= '`default_billing`="'. $tmp['default_billing']. '",';
    if(isset($tmp['password_hash'])) $strSql .= '`password_hash`="'. $tmp['password_hash']. '",';
    if(isset($tmp['confirmation'])) $strSql .= '`confirmation`="'. $tmp['confirmation']. '",';
    if(isset($tmp['dob'])) $strSql .= '`dob`="'. $tmp['dob']. '",';
    //if(isset($tmp['last_birthday'])) $strSql .= '`last_birthday`="'. $tmp['last_birthday']. '",';
    //if(isset($tmp['prefix'])) $strSql .= '`prefix`="'. $tmp['prefix']. '",';
    //if(isset($tmp['suffix'])) $strSql .= '`suffix`="'. $tmp['suffix']. '",';
    //if(isset($tmp['middlename'])) $strSql .= '`middlename`="'. $tmp['middlename']. '",';
    if(isset($tmp['firstname'])) $strSql .= '`firstname`="'. $tmp['firstname']. '",';
    if(isset($tmp['lastname'])) $strSql .= "`lastname`='". $tmp['lastname']. "',";
    if(isset($tmp['mobile'])) $strSql .= '`mobile`="'. $tmp['mobile']. '",';
            $strSql .= '`created_in`="'. $tmp['created_in']. '"';
            $strSql.= " where `entity_id`={$tmp['entity_id']}";
            //echo $strSql;die;
            $result= mysql_db_query($mysqlDatabase, $strSql, $conn);    // 执行sql查询
            
            if($result) { //下面是对原有映射表中的数据进行删除,请确保数据已经转移再进行删除!否则后果严重。
//                $model->addData(array(
//'is_check'=> null,
//'remain_gift_num'=> null,
//'rank_id'=> null,
//'vip_code'=> null,
//'reg_method'=> null,
//'store_code'=> null,
//'gender'=> null,
//'password_hash'=> null,
//'confirmation'=> null,
//'dob'=> null,
//'firstname'=> null,
//'lastname'=> null,
//'mobile'=> null,
//'mobile_cert'=> null,
//'created_in'=> null
//                ))->save();
            }
        }
    }


 3,将原来动态的属性转换为静态属性,

  update `{$this->getTable('eav_attribute')}` set `backend_type`='static' WHERE `entity_type_id` =1 and (
    `attribute_code` ='rank_id' or
    `attribute_code` ='gender' or
    `attribute_code` ='password_hash' or
    `attribute_code` ='confirmation' or
    `attribute_code` ='dob' or
    `attribute_code` ='reg_method' or
    `attribute_code` ='firstname' or
    `attribute_code` ='lastname' or
    `attribute_code` ='mobile' or
    `attribute_code` ='created_in'
    );

如上面看到的,只要backend_type设置为' static' ,eav 属性就自动转向 customer_entity 表了!是不是觉得:不愧是 magento啊!试一下后台的保存信息成功,前端登录成功,修改密码成功,添加产品,购物车优惠券,保存订单都没问题,松了一口气。但是实际上eav模块里面还是有一些写法写得不够规范,会造成一些模块的报错,如:customer用户保存时修改了用户密码会报错,前端忘记密码功能会报错,邮件订阅人会报错。。。幸好这些都很好修复。所以此方法有一定的风险,对于刚接触的朋友谨慎考虑。还有一个很重要的地方,当你发现更新eav_attribute错误的时候,千万不能 truncate eav_attribute; 再insert备份表数据, 这样会造成其他与之关联的记录被删除,记住 eav是心脏啊!这里提醒一下那些冲动的朋友们。你可以用以下语句进行恢复:

  update `{$this->getTable('eav_attribute')}` set `backend_type`='int' WHERE `entity_type_id` =1 and `attribute_code` ='rank_id';
  update `{$this->getTable('eav_attribute')}` set `backend_type`='int' WHERE `entity_type_id` =1 and `attribute_code` ='gender';
  update `{$this->getTable('eav_attribute')}` set `backend_type`='varchar' WHERE `entity_type_id` =1 and `attribute_code` ='password_hash';
  update `{$this->getTable('eav_attribute')}` set `backend_type`='varchar' WHERE `entity_type_id` =1 and `attribute_code` ='confirmation';
  update `{$this->getTable('eav_attribute')}` set `backend_type`='datetime' WHERE `entity_type_id` =1 and `attribute_code` ='dob';
  update `{$this->getTable('eav_attribute')}` set `backend_type`='int' WHERE `entity_type_id` =1 and `attribute_code` ='reg_method';
  update `{$this->getTable('eav_attribute')}` set `backend_type`='varchar' WHERE `entity_type_id` =1 and `attribute_code` ='firstname';
  update `{$this->getTable('eav_attribute')}` set `backend_type`='varchar' WHERE `entity_type_id` =1 and `attribute_code` ='lastname';
  update `{$this->getTable('eav_attribute')}` set `backend_type`='varchar' WHERE `entity_type_id` =1 and `attribute_code` ='mobile';
  update `{$this->getTable('eav_attribute')}` set `backend_type`='varchar' WHERE `entity_type_id` =1 and `attribute_code` ='created_in';


过程基本上是这样,这种方法大体上是遵循magento架构设计的,但对于eav 模块中写得不够规范的语句,还是会有一些报错,对系统熟悉的朋友自己修改一下就好。同样的道理,customer_address_entity也是可以这样修改的,这里不做列举。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值