Eliminando un cross join in SQL
-
27-10-2019 - |
Domanda
Sto cercando di ottimizzare una query che contiene un cross join. Ho query di grandi dimensioni che procedo per attraversare unirsi con una tabella derivata.
Sarebbe migliorare la velocità della query ruotando la tabella derivata in una vista? O anche l'acquisizione di tali informazioni in una tabella permanente?
Questa è la mia domanda
SELECT VIEWER_ID,
QUESTION_ID,
ANSWER_ID,
sum(ANSWER_SCORE) AS ANSWER_SCORE_SUMMED
FROM(SELECT cr.COMMUNICATIONS_ID AS ANSWER_ID,
cr.CONSUMER_ID as VIEWER_ID,
nc.PARENT_COMMUNICATIONS_ID AS QUESTION_ID,
case when cr.CONSUMER_ID= nc.SENDER_CONSUMER_ID then 3*((24/(((UNIX_TIMESTAMP(NOW())-UNIX_TIMESTAMP(cal.LAST_MOD_TIME)+3600)/3600))*(ces.EXPERT_SCORE * cirm.CONSUMER_RATING) + (12.5 * scs.SIMILARITY)* (1 - EXP(-0.5 * (cal.TIPS_AMOUNT / ATV.AVG_TIPS)) + .15)))
else ((24/(((UNIX_TIMESTAMP(NOW())-UNIX_TIMESTAMP(cal.LAST_MOD_TIME)+3600)/3600))*(ces.EXPERT_SCORE * cirm.CONSUMER_RATING) + (12.5 * scs.SIMILARITY)* (1 - EXP(-0.5 * (cal.TIPS_AMOUNT / ATV.AVG_TIPS)) + .15)))
end as ANSWER_SCORE
FROM (SELECT 234 AS CONSUMER_ID,
ACTION_LOG_ID,
COMMUNICATIONS_ID
FROM consumer_action_log
WHERE COMM_TYPE_ID=4) AS cr
JOIN network_communications AS nc
ON cr.COMMUNICATIONS_ID=nc.COMMUNICATIONS_ID
JOIN consumer_action_log AS cal
ON cr.ACTION_LOG_ID=cal.ACTION_LOG_ID
JOIN communication_interest_mapping AS cim
ON nc.PARENT_COMMUNICATIONS_ID=cim.COMMUNICATION_ID
JOIN consumer_interest_rating_mapping AS cirm
ON cr.CONSUMER_ID=cirm.CONSUMER_ID
AND cim.CONSUMER_INTEREST_EXPERT_ID=cirm.CONSUMER_INTEREST_ID
JOIN consumer_expert_score AS ces
ON nc.SENDER_CONSUMER_ID=ces.CONSUMER_ID
AND cim.CONSUMER_INTEREST_EXPERT_ID=ces.CONSUMER_EXPERT_ID
JOIN survey_customer_similarity AS scs
ON cr.CONSUMER_ID=scs.CONSUMER_ID_2
AND cal.SENDER_CONSUMER_ID=scs.CONSUMER_ID_1
OR cr.CONSUMER_ID=scs.CONSUMER_ID_1
AND cal.SENDER_CONSUMER_ID=scs.CONSUMER_ID_2
CROSS JOIN
(
SELECT AVG(cal.TIPS_AMOUNT) AS AVG_TIPS
FROM CONSUMER_ACTION_LOG AS cal
JOIN (SELECT 234 AS CONSUMER_ID,
ACTION_LOG_ID,
COMMUNICATIONS_ID
FROM consumer_action_log
WHERE COMM_TYPE_ID=4) AS cr
ON cal.SENDER_CONSUMER_ID=cr.consumer_id
) ATV) AS ASM
GROUP BY ANSWER_ID
ORDER BY ANSWER_SCORE_SUMMED DESC;
Si tratta di una lunga interrogazione, quindi non c'è bisogno di leggere tutto. Il succo è semplicemente che c'è un cross join. Sono nuovo di sql, ma mi è stato detto che croce unisce la velocità di rallentamento.
Soluzione
In quanto tale, la tua croce si uniscono non è molto più di un affare, perché la seconda interrogazione inline restituisce una sola riga.
La croce si unisce "a bassa velocità verso il basso" allo stesso modo come il caricamento dei rallenta auto giù velocità.
Lo fa, naturalmente, ma se avete bisogno di le cose si muovevano li si carica in una macchina, e se avete bisogno di un prodotto cartesiano, si fa un cross join.
Altri suggerimenti
Se la domanda è se di cross join più lento (quello che;?)?), Allora la risposta è sì semplificata. Naturalmente questa è una risposta molto generale a una domanda di carattere generale. Ma per te, è necessario quantificare lento.
Per tutti gli scopi pratici, la query potrebbe essere veloce come potrebbe essere. Quindi, per convalidare, eseguire spiegare piano per la query (io sono un ragazzo di Oracle, ma suppongo esecuzione spiegare piano in MySQL non è poi così diverso. Link http://dev.mysql.com/doc/refman/5.0/en/explain.html ).
Quindi creare una tabella temporanea e sostituire quelli nella vostra interrogazione e controllare di nuovo il piano.
. Nota: Se trovate la vostra spiegare il piano per la query abbastanza buono, non si deve perdere tempo per ulteriori analisi