Veuillez regarder ce tableau:
mysql> desc s_p;
+-------------------------+------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------------------------+------------------+------+-----+---------+----------------+
| id | int(10) unsigned | NO | PRI | NULL | auto_increment |
| s_pid | int(10) unsigned | YES | MUL | NULL | |
| sm_id | int(10) unsigned | YES | MUL | NULL | |
| m_id | int(10) unsigned | YES | | NULL | |
| created | datetime | YES | | NULL | |
| s_date | datetime | YES | | NULL | |
| estimated_date | datetime | YES | MUL | NULL | |
+-------------------------+------------------+------+-----+---------+----------------+
Jetez maintenant un œil à ces requêtes:
mysql> select count(*) from s_p where estimated_date is null;
+----------+
| count(*) |
+----------+
| 190580 |
+----------+
1 row in set (0.05 sec)
mysql> select count(*) from s_p where estimated_date is not null;
+----------+
| count(*) |
+----------+
| 35640 |
+----------+
1 row in set (0.07 sec)
mysql> select count(*) from s_p;
+----------+
| count(*) |
+----------+
| 1524785 |
+----------+
Les chiffres ci-dessus ne correspondent pas. Selon ma compréhension:
Count with IS NULL
et Count with IS NOT NULL
doivent être égaux à count lorsqu'ils sont interrogés sans clause where.
Une idée sur ce qui se passe ici?
================================================== =
Mise à jour du 17 février 2012
Depuis, j'ai constaté que beaucoup de gens se demandent quel type de valeurs a actuellement la date estimée. Voici la réponse:
mysql> select distinct date(estimated_date) from s_p;
+----------------------+
| date(estimated_date) |
+----------------------+
| NULL |
| 2012-02-17 |
| 2012-02-20 |
| 2012-02-21 |
| 2012-02-22 |
| 2012-02-23 |
| 2012-02-24 |
| 2012-02-27 |
| 2012-02-28 |
+----------------------+
9 rows in set (0.42 sec)
Comme vous pouvez le voir ci-dessus, la date_estimée a une valeur NULL ou une valeur datetime valide. Il n'y a pas de zéros ou de chaînes vides "".
Est-ce que cela (problème d'origine) peut se produire si l'index de la date estimée a des problèmes?
================================================== =
Mise à jour du 18 février 2012
Voici la sortie show create table:
| s_p | CREATE TABLE `s_p` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`s_id` int(10) unsigned DEFAULT NULL,
`sm_id` int(10) unsigned DEFAULT NULL,
`m_id` int(10) unsigned DEFAULT NULL,
`created` datetime DEFAULT NULL,
`estimated_date` datetime DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `sm_id` (`sm_id`),
KEY `estimated_date_index` (`estimated_date`) USING BTREE,
) ENGINE=InnoDB AUTO_INCREMENT=1602491 DEFAULT CHARSET=utf8 |
Encore une fois, je ne peux que soupçonner l'index de la date estimée ici.
De plus, la version du serveur mysql est 5.5.12.
select count(*)
pas et nonselect count(estimated_date)
? Ces deux résultats renverront des résultats différents car les valeurs NULL sont ignorées si c'est la seule chose que vous comptez.SELECT COUNT(*),SUM(CASE WHEN estimated_date IS NULL THEN 1 ELSE 0 END),SUM(CASE WHEN estimated_date IS NOT NULL THEN 1 ELSE 0 END) from s_p
lancer : - qui devrait obtenir tous les décomptes en une seule fois.CHECK TABLE
? Compte tenu de la manière extravagante compte complet de la ligne plus grande, je suppose un estDELETE
allé quelque part fou.Réponses:
Avez-vous des dates nulles? Les valeurs Datetime de
0000-00-00 00:00:00
sont considérées par MySQL pour satisfaire simultanémentis null
etis not null
:Voir: http://bugs.mysql.com/bug.php?id=940
Ceci est classé comme "pas un bug". Ils suggèrent une solution de contournement: utilisez le mode strict, qui convertira l'avertissement d'insertion en erreur.
Cela dit, cela ne peut à lui seul expliquer la variation sauvage des résultats que vous obtenez (la somme des chiffres
is null
etis not null
doit dépasser le nombre illimité) ...la source
DATE
ouDATETIME
est défini commeNOT NULL
. Dans la question ici, la colonne est définie comme nullable. Ce bogue est cependant une autre raison d'exécuter MySQL en mode strict uniquement.@ypercube:
On m'a récemment demandé si je pensais que le bogue de régression "SELECT COUNT (DISTINCT) plante InnoDB lorsque l'opérande est dans la clé primaire ou l'index unique" pourrait être à l'origine de cela.
Voici ma réponse (à l'origine ici):
http://www.chriscalender.com/?p=315&cpage=1#comment-1460
Je ne pense pas que ce soit le même bug. Ce bogue concerne davantage le plantage et nécessite spécifiquement SELECT COUNT (DISTINCT), plus l'opérande WHERE se trouve dans la clé primaire ou l'index Unique.
Votre bogue / problème n'a pas le DISTINCT, il ne plante pas et l'index sur la colonne datetime n'est pas une clé primaire ni unique. Cependant, c'est un peu étrange, donc j'ai fait quelques recherches et j'ai rencontré ce bogue, qui semble plus susceptible d'être impliqué / lié:
http://bugs.mysql.com/bug.php?id=60105
En fait, il est désigné comme «pas un bug», mais il montre / décrit comment vous pouvez rencontrer un comportement étrange lorsque vous avez des dates / heures avec «0000-00-00» et en utilisant IS NULL et IS NOT NULL.
Je me demande si vous avez une de ces lignes «0000-00-00» qui pourrait affecter les comptes?
Notez que le développeur qui commente dans le rapport de bogue mentionne également cette page:
Si ce n'est pas le cas, je recommanderais certainement de mettre à niveau et d'essayer cela sur la dernière version 5.5, qui est 5.5.21 (au 22/02/2012), car cela fait 9 mois (et 9 versions) depuis 5.5.12 a été libéré.
Notez que vous devriez pouvoir vider la table (et les données) et l'importer dans une autre instance de test, juste pour la tester. De cette façon, vous n'affectez pas une machine de production et vous pouvez configurer une instance de test en quelques minutes.
Ensuite, si cela ne fait toujours pas de différence, vous seriez en mesure de tester d'autres éléments, tels que peut-être convertir la table en MyISAM pour voir si le problème est global ou spécifique à InnoDB.
Ou, j'ai remarqué que l'index de la "date_estimée" était:
KEY
estimated_date_index
(estimated_date
) UTILISATION DE BTREENotez la «UTILISATION DE BTREE». Peut-être essayez-le sans UTILISER BTREE et voyez si vous voyez toujours le même comportement. (Ou supprimez complètement l'index juste pour tester .. tout cela aidera à réduire le problème).
J'espère que cela t'aides.
la source
Essayez la requête
la source
Je vois quelque chose d'intéressant dans la disposition du tableau qui crie «Je n'ai pas envie de compter». Ce que je vais dire n'est qu'un pressentiment.
Vous avez exécuté cette requête avant
Exécutez-le en tant que COUNT / GROUP BY
Vous devez obtenir le nombre définitif que vous recherchiez.
Pourtant, pourquoi les nombres pour NULL et NOT NULL seraient-ils calculés correctement? Encore une fois, ce n'est qu'une supposition éclairée.
Vous avez la colonne
estimated_date
indexée. Voici ce que je veux que vous essayiez:Ce n'est pas une faute de frappe. Je veux que tu cours
SHOW INDEX FROM s_p;
quatre (4) fois. Regardez laCardinality
colonne. Depuis la tables_p
dans InnoDB, je m'attends à ce que la colonne Cardinalité soit différente à chaque fois. Pourquoi?InnoDB obtient la valeur de cardinalité en l'estimant (NO PUN INTENDED) en comptant via les entrées de la page BTREE. Vérifiez votre variable système innodb_stats_on_metadata . Il doit être activé. S'il est déjà activé, désactivez-le et réexécutez vos requêtes d'origine pour voir si cela améliore les choses. FAITES CECI UNIQUEMENT COMME DERNIER RESORT !!!
Donc, au lieu de ces requêtes:
Essayer
Cela devrait vous donner le nombre de lignes avec une date estimée non nulle.
Une autre approche que vous voudrez peut-être expérimenter avec cette requête de force brute à l'aide de la fonction ISNULL :
J'espère que ces suggestions aident !!!
la source
C'est attendu. Pour une colonne qui peut être annulée, 0 == NULL = "" et ainsi de suite. Ainsi, la première vérification renvoie en fait des lignes où aucune date n'a été définie ou son analogue à "0 / NULL"
la source
0
n'est jamais égal àNULL
. La chaîne vide (''
) n'est pas la même que lesNULL
deux, sauf si vous travaillez avec Oracle.