Jestem wpuszczonym nowicjuszem w interfejsie API Entity, ale próbuję to wyleczyć. Pracuję nad witryną, która wykorzystuje wiele typów treści z dołączonymi do nich różnymi polami; nic fajnego. Tak więc, gdy chcę pobrać zestaw wpisów, w swojej ignorancji dzwoniłem bezpośrednio do bazy danych i robiłem coś takiego:
$query = db_select('node', 'n')->extend('PagerDefault');
$query->fields('n', array('nid'));
$query->condition('n.type', 'my_content_type');
$query->leftJoin('field_data_field_user_role', 'role', 'n.nid = role.entity_id');
$query->condition('role.field_user_role_value', $some_value);
$query->leftJoin('field_data_field_withdrawn_time', 'wt', 'n.nid = wt.entity_id');
$query->condition('wt.field_withdrawn_time_value', 0);
$query->orderBy('n.created', 'desc');
$query->limit(10);
$result = $the_questions->execute()->fetchCol();
(tak, prawdopodobnie mógłbym zwinąć kilka z tych wierszy w jedno $the_questions->
zdanie; pls zignoruj to na razie.)
Próbując przepisać to za pomocą EntityFieldQuery, wymyślam:
$query = new EntityFieldQuery();
$query
->entityCondition('entity_type', 'node')
->entityCondition('bundle', 'my_content_type')
->fieldCondition('field_user_role', 'value', $some_value)
->fieldCondition('field_withdrawn_time', 'value', 0)
->propertyOrderBy('created', 'desc')
->pager(10);
$result = $query->execute();
if (isset($result['node'])) {
$result_nids = array_keys($result['node']);
}
else {
$result_nids = array();
}
co daje mi pożądane wyniki i jest z pewnością ładniejsze.
Więc teraz zastanawiam się nad wydajnością. Na początek wrzucam każdy z tych fragmentów kodu do głupiej for()
pętli, przechwytując time()
przed i po wykonaniu. Każdą wersję uruchamiam 100 razy na niezbyt dużej bazie danych i otrzymuję coś takiego:
- Wersja bezpośrednia: 110 ms
- Wersja EFQ: 4943 ms
Oczywiście po ponownym uruchomieniu testu otrzymuję różne wyniki, ale wyniki są konsekwentnie w tym samym parku.
Yikes. Czy robię tu coś złego, czy to tylko koszt korzystania z EFQ? Nie przeprowadziłem żadnego specjalnego strojenia bazy danych w odniesieniu do typów treści; wynikają one ze zdefiniowania typów treści w zwykły sposób oparty na formularzach. jakieś pomysły? Kod EFQ jest zdecydowanie czystszy, ale naprawdę nie sądzę, że mogę sobie pozwolić na 40-krotny wzrost wydajności.
->addTag('node_access')
w zapytaniu ??). Zmieniłem zapytanie „bezpośrednie” za pomocą znacznika node_access, a czasy wykonania są znacznie bliższe: czas EFQ jest teraz tylko o współczynnik 2 większy niż bezpośrednie podejście, co wygląda rozsądnie, biorąc pod uwagę względne SQL, które wypompowują oba ( Mogę pisać, jeśli ludzie nadal się przejmują). (ciąg dalszy od następnego komentarza ....)