2017-09-30 24 views
0

J'ai besoin d'auditer certaines données, mais je suis en train de tomber sur un roadblock avec une requête qui ne retourne pas. Que puis-je faire différemment ici car je ne comprends vraiment pas ce que ces requêtes retournent (exécutées à partir de mysql workbench) même après les avoir laissées s'exécuter pendant plusieurs heures? Suis-je juste sous provisioned?Google Cloud SQL sélection des lignes qui n'existent pas dans une autre table

J'ai une instance sql cloud 4 standard n1 4 (4cpu, 15GB ram). Les deux tables sont ci-dessous. Il existe également un index sur customer_id pour la table un. Le tableau 2 contient 885481 lignes et le tableau 1 contient 1891653 lignes.

J'ai essayé trois variantes d'une requête pour rechercher des ID client dans la table 1, où elles n'existent pas dans la table 2 (représentée par account_group_id).

Ce que je me serais attendu à être plus performants et retourner réellement:

Select customer_id 
FROM Table1 as a 
WHERE NOT EXISTS(
    Select account_group_id 
    FROM Table2 as b WHERE b.account_group_id = a.customer_id 
) 

En tant que sous requête:

Select customer_id 
FROM Table1 
WHERE customer_id NOT IN(
    Select account_group_id 
    FROM Table2 
) 

comme une jointure gauche:

SELECT customer_id 
FROM Table1 as a 
LEFT OUTER JOIN Table2 as b ON a.customer_id = b.account_group_id 
WHERE b.account_group_id IS NULL 

EDIT: Donc, après quelques bricolages et en fait en utilisant EXPLAIN avant de poster ma question, la table2 subq uery effectue une analyse FULL TABLE pour une raison quelconque. J'ai essayé cette requête sur mes environnements de test/de transfert avec le même index et j'y vois un index. Maintenant, je suis encore plus confus. full table scan

Même si j'ajoute un indice d'indice de force, l'optimiseur de requête refuse d'utiliser la clé primaire.

C'est ce que le plan de requête ressemble à mon environnement de mise en scène:

enter image description here

Toute pensée pourquoi cela se produit?

Tableau 1:

Table 1

Tableau 2:

Table 2

+0

dans la troisième variante, vous avez besoin d'une jointure gauche – soft87

Répondre

0

bien après beaucoup bricoler je complètement retravaillé cette requête pour faire l'optimiseur idiot utiliser l'index que je voulais ...doit être quelque chose à voir avec la taille des tables:

SELECT a.customer_id 
FROM Table1 as a 
WHERE a.customer_id NOT IN (
    SELECT b.customer_id 
    FROM Table1 as b 
    JOIN (select account_group_id from Table2) as x on x.account_group_id = b.customer_id 
) 
2

Deux choses:

  1. Assurez-vous que la table 2 a un index sur account_group_id. Sinon, vous effectuez un scan de table complet, pas efficace. L'option SUB QUERY est la meilleure option, mais pas OUTER JOIN car elle multiplie les deux lignes de tables ensemble, obtenant un jeu de résultats horrible (et apparemment sans fin!).

Si l'index n'existe pas

-- CREATING AN INDEX IN CASE 
CREATE INDEX T2_agi ON Table2(account_group_id);  

SELECT customer_id 
FROM Table1 as a 
WHERE customer_id NOT IN(
    Select account_group_id 
    FROM Table2 
); 
+0

Merci, je vais essayer. Il n'y a pas d'index sur le compte_group_id, mais c'est la clé primaire. J'ai peut-être un malentendu ici parce que j'avais compris que la clé primaire remplirait cette condition. – Jesse

+0

Oui, la 'PRIMARY KEY' est en fait le meilleur' INDEX'. Essayez un 'EXPLAIN' sur la requête. La syntaxe est fondamentalement coller le mot 'EXPLAIN' devant la requête! –

+0

Merci pour l'aide. J'aurais dû utiliser expliquer avant de poster ma question. Il est assez clair que l'index primaire est ignoré pour une raison quelconque sur la sous-requête selon mes modifications. Des pensées comme trop quoi essayer? – Jesse