Me han encargado que reescriba una consulta lenta. Resolví mi problema de rendimiento, sin embargo, estoy inquieto porque no entiendo por qué uno de los enfoques que probé es más rápido que el otro.
Consulta 1 (tarda ~13 segundos en el sitio web, ~0,2 segundos en PHPMYADMIN):
SELECT t.USER_ID, COUNT(DISTINCT r1.id1) as count_matches FROM b_squad_member_result as t INNER JOIN (SELECT m.IBLOCK_ELEMENT_ID as id1, (m.IBLOCK_ELEMENT_ID + 2) as id2, (m.IBLOCK_ELEMENT_ID + 4) as id3 FROM b_iblock_element_prop_s3 as m WHERE m.PROPERTY_8 IS NULL) as r1 ON t.MATCH_ID IN(id1, id2, id3) INNER JOIN b_uts_user as u ON u.VALUE_ID = t.USER_ID AND u.UF_ID_TEAM = 2228 GROUP BY t.USER_IDPlan de ejecución de la Consulta 1
Consulta 2 (tarda ~0,2 segundos en el sitio web, ~0,2 segundos en PHPMYADMIN):
SELECT t.USER_ID, COUNT(DISTINCT r1.id1) as count_matches FROM b_squad_member_result as t INNER JOIN (SELECT m.IBLOCK_ELEMENT_ID as id1, (m.IBLOCK_ELEMENT_ID + 2) as id2, (m.IBLOCK_ELEMENT_ID + 4) as id3 FROM b_iblock_element_prop_s3 as m WHERE m.PROPERTY_8 IS NULL) as r1 ON t.MATCH_ID = id1 OR t.MATCH_ID = id2 OR t.MATCH_ID = id3 INNER JOIN b_uts_user as u ON u.VALUE_ID = t.USER_ID AND u.UF_ID_TEAM = 2228 GROUP BY t.USER_IDPlan de ejecución de la consulta 2:
Primero fui con la Consulta 1 ya que en PHPMYADMIN cumplía con mis expectativas de rendimiento. Sin embargo, en el sitio web en sí, la consulta tomó mucho más tiempo. Después de probar muchas soluciones diferentes, decidí cambiar la cláusula IN para t.MATCH_ID = id1 O t.MATCH_ID = id2 O t.MATCH_ID = id3 y esto funciona tan rápido como se supone que debe hacerlo. Sin embargo, me gustaría entender por qué el segundo enfoque es más rápido. He leído que la cláusula IN se transforma en varias cláusulas OR antes de la ejecución real. ¿Realmente puede afectar tanto al rendimiento?
Los paréntesis son diferentes. Su primera consulta coloca los paréntesis alrededor de r1 con el ON adentro; sería exterior, como hiciste con la segunda consulta.
Veo que los EXPLAINs son diferentes; No sé si esto es por los padres o IN vs OR.
Probar un valor en varias columnas es realmente malo para el rendimiento. Por lo general, se puede corregir mediante un cambio de esquema. Llamo al antipatrón "rociar una matriz en columnas". Por lo general, es mejor tener otra tabla con [hasta] 3 filas para esas identificaciones. Si los identificadores son cadenas, FULLTEXT puede ser un mejor enfoque.
Si bien el párrafo anterior es válido en general, no se aplica en su caso, ya que idn se calcula a partir de una sola columna IBLOCK_ELEMENT_ID . WTF?
Realmente necesito ver SHOW CREATE TABLE para ayudarte por completo.
Estos índices, si aún no los tiene, pueden ayudar:
u: (UF_ID_TEAM, VALUE_ID) m: (PROPERTY_8, IBLOCK_ELEMENT_ID) COUNT(DISTINCT r1.id1) -- DISTINCT (y su sobrecarga) probablemente podría hacerse mejor agregando un GROUP BY a la tabla derivada para r1 . Bueno, eso puede no ser útil, depende de si hay varias filas de u involucradas. Pero luego nos adentramos en si tropezará con ONLY_FULL_GROUP_BY . Entonces, explique si las tablas son 1: muchos o 1: 1.
(Estoy de acuerdo en que esta es una pregunta XY).