Primeiramente, há um problema com sua consulta. Você usa LEFT JOIN, mas se transforma em um INNER JOIN implícito com sua cláusula where:AND (a.list_in='store' OR u.shop_active='1')
Por que isso transforma o LEFT JOIN em um INNER implícito? Porque o LEFT JOIN produzirá valores NULL para u.shop_active quando não houver usuário correspondente, mas NULL NUNCA será igual a '1'. Isso transforma a consulta em um INNER JOIN porque todas as linhas produzidas pelo OUTER JOIN serão filtradas pela condição WHERE.
Esse filtro também é o motivo do problema de desempenho. Você tem uma condição OR entre colunas em duas tabelas diferentes. Não há índice que possa satisfazer tal condição.
Aqui está outra maneira que pode ter um desempenho melhor. Esta versão só busca por listagens onde (a.list_in !='store' e u.shop_active ='1') quando houver menos de 12 list_in='store' listagens.
Para usar o seguinte, certifique-se de ter um índice em (list_in, end_time)
SELECT * FROM
(
SELECT a.listing_id, a.name, a.item_price, a.max, a.nb, a.currency,
a.end_time, a.closed, a.bold, a.hl, a.buy_price, a.is_offer, a.reserve,
a.owner_id, a.postage_amount, a.fb_current_bid, a.type, a.start_time,
a.is_relisted_item, a.enable
FROM db_listings a
WHERE list_in = 'store'
a.active=1 AND
a.approved=1 AND
a.deleted=0 AND
a.creation_in_progress=0 AND
a.closed=0
ORDER BY end_time
LIMIT 12
)
UNION ALL
(
SELECT a.listing_id, a.name, a.item_price, a.max, a.nb, a.currency,
a.end_time, a.closed, a.bold, a.hl, a.buy_price, a.is_offer, a.reserve,
a.owner_id, a.postage_amount, a.fb_current_bid, a.type, a.start_time,
a.is_relisted_item, a.enable
FROM db_listings a
JOIN users u
ON a.owner_id = u.user_id
AND u.shop_active = '1'
WHERE list_in != 'store' AND
a.active=1 AND
a.approved=1 AND
a.deleted=0 AND
a.creation_in_progress=0 AND
a.closed=0
ORDER BY end_time
LIMIT 12
)
) sq
ORDER BY list_in, end_time
LIMIT 12;