我有这两个查询,第一个是使用Active Record
编写的,第二个是使用yii\db\Query
自定义的。在我使用Query编写的localhost查询中,查询速度提高了2-4毫秒,但更难编写。用AR编写的查询也将执行多个数据库查询以及SHOW CREATE TABLE,总共就像执行AR时执行的更多或10个查询。 Plus AR要求您为关系网络中的每个表定义AR模型,而如果您避免AR,则最终会在您的应用中使用较少的类/文件。
我的问题是,您会使用AR还是会使用yii\db\Query
撰写查询? AR更漂亮,更容易编写,但它产生了很多查询,这是一个问题吗?我正在一个桌子上有几百万行的网站上工作,每天大约有10万次网站访问。
AR查询:
return self::find()->select('id, news_users_id')
->with([
'newsUsers' => function ($query) {
$query->select(['ID', 'cmpid']);
},
])
->with([
'newsUsers.firme' => function ($query) {
$query->select(['id', 'skraceni_naziv']);
},
])
->with([
'newsUsers.firmeBh' => function ($query) {
$query->select(['id', 'skraceni_naziv']);
},
])
->with([
'newsUsers.firmeOstalo' => function ($query) {
$query->select(['id', 'skraceni_naziv']);
},
])
->orderBy(['id' => SORT_DESC])
->limit(6)
->all();
查询:
$query = new Query;
$query->select(['club.id',
'firme.id', 'firme.skraceni_naziv',
'firme_bh.id', 'firme_bh.skraceni_naziv',
'firme_ostalo.id', 'firme_ostalo.skraceni_naziv'])
->from('club')
->innerJoin('news_users', 'club.news_users_id = news_users.ID')
->leftJoin('firme', 'news_users.cmpid = firme.id')
->leftJoin('firme_bh', 'news_users.cmpid = firme_bh.id')
->leftJoin('firme_ostalo', 'news_users.cmpid = firme_ostalo.id')
->orderBy(['club.id' => SORT_DESC])
->limit(6);
$command = $query->createCommand();
return $command->queryAll();
答案 0 :(得分:4)
首先,可以缓存您的架构并避免那些“SHOW CREATE TABLE”查询。使用enableSchemaCache
对象的db
属性进行设置。
其次,连接并不总是填充相关记录的最佳方式。例如,如果表A中的每个条目在表B中具有许多相关条目,则将B加入A将导致来自表A的条目被重复。这可能是性能问题。
因此yii2有with()
和joinWith()
。使用with()
获取相关表将进行2次查询,但更多时候这样做会更有效。
最后,一旦掌握了AR,AR就是一个非常方便的工具。对我来说,它的好处超过了开销。
答案 1 :(得分:3)
首先:ActiveRecord :: find()方法返回扩展Query类的ActiveQuery实例。因此,您可以使用ActiveRecord :: find()使用Query对象执行的所有操作。
不同之处在于:ActiveQuery有一些额外的方法,包括'with'方法,它与'join'方法不同,因为它运行了你已经知道的额外数据库请求。使用ActiveQuery和'with'方法的结果是ActiveRecord对象作为主要结果及其关系。在另一方面,Query将仅返回数据库数据作为数组,因此您将错过ActiveRecord方法。
如果性能很重要,最好通常使用连接,因为它只需要一个db请求。但是很多联合数据对性能也很重要。因此,如果您遇到性能问题,我相信您需要做出一些特别的决定。