2014-06-17 6 views
0

Mes tables db sont en croissance très rapide (et continuera), à ce moment j'ai un problème avec cette requête (bien, d'autres aussi):Mysql: Optimiser requête sur les tables énormes

select user_id from post where user_id not in (select id from user) 

Ce que je dois est les nouveaux identifiants qui sont dans la table de la poste et il n'y a pas de table utilisateur.

est l'expliquer ici:

> mysql> explain select user_id from post where user_id not in (select 
> id from user); 
> 

+----+--------------------+-------+-----------------+---------------+---------+---------+------+----------+-------------+ 
| id | select_type  | table | type   | possible_keys | key  | key_len | ref |rows  | Extra  | 
+----+--------------------+-------+-----------------+---------------+---------+---------+------+----------+-------------+ 
| 1 | PRIMARY   | post | ALL    | NULL   |NULL  | NULL | NULL | 16076920 | Using where | 
| 2 | DEPENDENT SUBQUERY | user | unique_subquery | PRIMARY  | PRIMARY | 8  | func |  1 | Using index | 
+----+--------------------+-------+-----------------+---------------+---------+---------+------+----------+-------------+ 

J'ai essayé d'autres aussi:

SELECT p.user_id FROM post p LEFT JOIN user u ON p.user_id=u.id WHERE u.id IS NULL; 

L'expliquer:

mysql> EXPLAIN SELECT p.user_id FROM post p LEFT JOIN user u ON p.user_id=u.id WHERE u.id IS NULL; 
+----+-------------+-------+--------+---------------+---------+---------+-----------------+----------+--------------------------------------+ 
| id | select_type | table | type | possible_keys | key  | key_len | ref    | rows  | Extra        | 
+----+-------------+-------+--------+---------------+---------+---------+-----------------+----------+--------------------------------------+ 
| 1 | SIMPLE  | p  | ALL | NULL   | NULL | NULL | NULL   | 14323335 |          | 
| 1 | SIMPLE  | u  | eq_ref | PRIMARY  | PRIMARY | 8  | ghost.p.user_id |  1 | Using where; Using index; Not exists | 
+----+-------------+-------+--------+---------------+---------+---------+-----------------+----------+--------------------------------------+ 

Les deux requêtes doivent voir le poste tableau au complet, et il est très énorme: tableau de la poste: 16077899 entrées table de l'utilisateur: 9657158 entrées

La requête prend plusieurs minutes (plus de 30 minutes) à effectuer, une astuce?

Merci!

+1

Votre deuxième requête devrait renvoyer beaucoup de lignes nulles, puisque u.id ne s'affichera que s'il est nul. Peut-être que vous voulez p.user_id à la place. Est-ce qu'il fonctionne aussi lentement que la première requête? –

+0

Pouvez-vous ajouter la table déclare s'il vous plaît? – Kickstart

+0

Joachim, tu as raison, j'ai changé la deuxième requête. – user3364621

Répondre

0

Je pense que vous devriez faire deux choses ...

  1. Assurez-vous que vous avez et l'index sur le poteau (user_id)
  2. Ajouter le mot-clé DISTINCT à votre requête, comme ceci:

    SELECT DISTINCT user_id DE poste OÙ user_id PAS (SELECT id FROM user)

Vérifiez le nouveau PLAN EXPLAIN.

+0

en ajoutant l'index, ça va prendre du temps ... il y a 14M lignes. – user3364621

+0

Vous demandez une optimisation ... l'ajout d'un index peut en valoir la peine.Soyez patient;) – Frazz

+0

Je ne pense pas que l'index aidera pour cette requête (pourrait bien pour d'autres requêtes sur la table). Il s'agit toujours de la table primaire dans la jointure (donc aucun enregistrement n'est recherché sur cette table pour correspondre à une valeur) et rien n'est vérifié pour cette valeur qui limitera la requête. – Kickstart

0

Je ne suis pas expert en base de données, mais votre première requête d'explication n'a pas utilisé d'index sur userid, avez-vous un index construit sur le champ user_id dans la table post? Si ce n'est pas juste créer ça. En outre, vous pouvez essayer de grouper par/distinct pour filtrer vos utilisateurs, car la première requête renvoie sinon plusieurs ID utilisateur à partir de la publication. Cette augmentation de la vitesse en tout.

+0

ajoutant l'index à la table. – user3364621