PHP - Optimizar consultas

 
Vista:
sin imagen de perfil

Optimizar consultas

Publicado por David (1 intervención) el 28/09/2022 15:57:37
Buenas, tengo un código con 5 consultas SQL, quería saber si en un futuro se pondrá lento si estas consultas llegan a lidiar con millones de registros? Si no esta bien estructurado alguien podría ayudarme a optimizarlo bien unificando las consultas o lo que sea? Muchas gracias.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
<?php
        $perPage = 12;
	if($result["url"] == "informatica") { $search = "WHERE cat LIKE '%PC /%' OR cat LIKE '%Almacenamiento%' OR cat LIKE '%Componentes%' OR cat LIKE '%Conectividad y redes%' OR cat LIKE '%Periféricos >%' OR cat LIKE '%Tintas / Toners%' OR cat LIKE '%Ópticos >%' OR cat LIKE '%Lectores y escáneres%' OR cat LIKE '%Monitores y accesorios%' OR cat LIKE '%Periféricos de PC%' OR cat LIKE '%Proyectores y pantallas%' OR cat LIKE '%Tablets y accesorios%'"; }
	if($result["url"] == "componentes-de-pc") { $search = "WHERE cat LIKE '%Componentes%'"; }
										   $stmt = $pdo->prepare("SELECT count(*) as num_rows FROM products $search");
		$stmt->execute();
		$row = $stmt->fetch(PDO::FETCH_ASSOC);
        $total_results = $row['num_rows'];
 
    $total_pages = ceil($total_results / $perPage);
 
    // Current page
    $page = isset($_GET['page']) ? $_GET['page'] : 1;
    $starting_limit = ($page - 1) * $perPage;
 
	$stmt1 = $pdo->prepare("SELECT name,img,id FROM products $search ORDER BY id DESC LIMIT $starting_limit,$perPage");
	$stmt1->execute();
 
 
 
	while ($i = $stmt1->fetch(PDO::FETCH_ASSOC)) {
	$a = $pdo->prepare("SELECT shop_id, url, MIN(pvp) as minimo FROM products_shops WHERE product_id=".$i["id"]."");
	$a->execute();
		$a = $a->fetch(PDO::FETCH_ASSOC);
		if($a["shop_id"]>1) {
		$b = $pdo->prepare("SELECT shop_name FROM shops WHERE id=".$a["shop_id"]."");
	$b->execute();
		$b = $b->fetch(PDO::FETCH_ASSOC);
		}
		$count = $pdo->prepare("SELECT COUNT(*) as num_rows FROM products_shops WHERE product_id=".$i["id"]."");
		$count->execute();
		$row = $count->fetch(PDO::FETCH_ASSOC);
        $totalRowCount = $row['num_rows'];
			if(isset($b["shop_name"]) && decrypt($b["shop_name"],$key)=="opirata") { $pvp = $a["minimo"]; } else { $pvp = $a["minimo"]; }
		?>
	<div class="widget">
    <div class="widgetImage">
      <img src="<?php echo $i["img"]; ?>" alt="<?php echo $i["name"]; ?>" />
    </div>
    <div class="widgetContent">
		<span class="cap t12 bold"><?php if(isset($b["shop_name"])) { echo decrypt($b["shop_name"],$key); } else { echo "No hay ofertas"; } ?></span>
      <h2 class="widgetTitle"><?php echo substr($i["name"], 0, 77); if(strlen($i["name"]) > 77) { echo "..."; } ?></h2>
 
		<span class="price t18 bold"><?php if($pvp>0) { echo $pvp; } else { echo 0; } ?></span><span class="t11 right1">(Envío incluido)</span><br/><div class="sop"><?php if($totalRowCount>1) { ?><span class="icon-check green t16"></span> <?php } ?>
		<span class="t12"><?php if($totalRowCount>1) { ?>El precio más bajo<?php } elseif($totalRowCount==1) { ?>Único precio disponible<?php } else { ?>No hay ofertas<?php } ?></span></div>
		<br/><br/><a href="<?php echo $a["url"]; ?>" target="_blank" title="<?php if($totalRowCount>1) { ?>Ir a la mejor oferta<?php } else { ?>Ir a la oferta<?php } ?>" rel="nofollow"><div class="snd"><?php if($totalRowCount>1) { ?>Ir a la mejor oferta<?php } else { ?>Ir a la oferta <?php } ?></div></a><hr/>
 
		<?php if($totalRowCount>1) { ?><div id="<?php echo $i['id']; ?>" class="snd2" onclick="shops(this.id);" title="Ver <?php echo $totalRowCount; ?> ofertas"><div class="numtotal"><?php echo $totalRowCount; ?></div><span class="icon-store"></span> </div><?php } elseif($totalRowCount==0) { ?> <div id="<?php echo $i['id']; ?>" class="snd2" title="No hay ofertas" onclick="shops(this.id);"><div class="numtotal"><?php echo $totalRowCount; ?></div><span class="icon-store"></span></div> <?php } else { ?><div id="<?php echo $i['id']; ?>" class="snd2" title="Ver <?php echo $totalRowCount; ?> oferta" onclick="shops(this.id);"><div class="numtotal"><?php echo $totalRowCount; ?></div><span class="icon-store"></span></div> <?php } ?><div id="<?php echo $i['id']; ?>" class="snd2" onclick="shops(this.id);" title="Información y características"><span class="icon-list"></span> </div><div id="<?php echo $i['id']; ?>" class="snd2" onclick="shops(this.id);" title="Reseñas"><span class="icon-comment"></span> </div><div id="<?php echo $i['id']; ?>" class="snd2" onclick="shops(this.id);" title="Alerta de precio"><span class="icon-alarm"></span> </div><div id="<?php echo $i['id']; ?>" class="snd2" onclick="shops(this.id);" title="Historial de precios"><span class="icon-stats"></span> </div>
    </div>
  </div>
 
	<?php
	}
?>
Valora esta pregunta
Me gusta: Está pregunta es útil y esta claraNo me gusta: Está pregunta no esta clara o no es útil
0
Responder
Imágen de perfil de Ivan

Optimizar consultas

Publicado por Ivan (118 intervenciones) el 02/10/2022 10:18:01
Hola,

el tema de optimizar consultas Mysql es verdaderamente interesante y no siempren tiene la misma solución, porque cada DB es un mundo, con sus jerarquías, campos, índices y consultas.

Cuando empecé con mi web Gestor Ligas quería precisamente profundizar en Mysql y me metí en un proyecto que actualmente tiene 38 tablas relacionadas entre sí, que ofrecen consultas muy optimizadas y algunas tablas tienen mas de 1.3millones de registros.

Una web que me fué muy bién para entender las optimizaciones es https://www.adictosaltrabajo.com/2016/10/24/optimizacion-de-consultas-en-mysql/

En cuanto a tus consultas, partiendo de la base que pueden tener millones de registros te puedo decir varias cosas:

- Evita hacer tanto LIKE '%PC' etc. esto será lentísimo a la larga. Intenta crear un índice para cada subcategoría

- Evita hacer OR. Cada vez que utilizas OR tiras por la ventana cualquier índice.

- Evita hacer ORDER BY id y luego LIMIT inicio, fin. Si tienes un millon de registros primero los ordena y luego aplica el recorte. Además el ID si se trata de un índice generado automáticamente por Mysql, ya está en orden. Un truco es que al paginar el enlace de cada página apunte al id anterior y siguiente (de cada página), y en límit simplemente pones el total de registros a mostrar por página. Entonces Mysql sólo leerá XX registros a partir de ese id.

Cuando digo "evita" me refiero a buscar alternativas, si no es posible, busca cómo mejorar la consulta, a veces se trata de minificar los daños.

Para saber si tus consultas son efectivas utiliza EXPLAIN y estudia cómo mejorar la consulta. Espero que todo esto te sirva.

Un saludo!
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
1
Comentar