it-swarm-eu.dev

MySQL IS NULL / IS NENÍ NULL Chybí?

Podívejte se prosím na tuto tabulku:

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    |                |
+-------------------------+------------------+------+-----+---------+----------------+

Nyní se podívejte na tyto dotazy:

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 |
+----------+

Výše uvedené hodnoty se neshodují. Podle mého porozumění:

Počítejte s IS NULL a počítejte s IS NOT NULL by se mělo rovnat počtu při dotazu bez klauzule where.

Máte představu o tom, co se tady děje?

================================================== =

Aktualizace dne 17. února 2012

Od té doby jsem zjistil, že spousta lidí se ptá na to, jaké hodnoty má odhadované datum aktuálně. Zde je odpověď:

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)

Jak můžete vidět výše, odhadovaný datum má buď NULL, nebo platné hodnoty datetime. Neexistují žádné nuly ani prázdné řetězce.

Může k tomu dojít (původní problém), pokud má index v odhadovaném datu nějaké problémy?

================================================== =

Aktualizace dne 18. února 2012

Zde je výstup tabulky vytvoření show:

 | 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 |

Opět mohu podezření z indexu odhadnout pouze zde.

Verze serveru mysql je také 5.5.12.

18
user1213259

Máte nějaké nulové rande? Hodnoty datetime 0000-00-00 00:00:00 jsou MySQL považovány za současně uspokojující is null a is not null:

[email protected]@localhost > create temporary table _tmp (a datetime not null);
Query OK, 0 rows affected (0.02 sec)

[email protected]@localhost > insert into _tmp values ('');
Query OK, 1 row affected, 1 warning (0.00 sec)

Warning (Code 1264): Out of range value for column 'a' at row 1
[email protected]@localhost > select a from _tmp where a is null;
+---------------------+
| a                   |
+---------------------+
| 0000-00-00 00:00:00 |
+---------------------+
1 row in set (0.00 sec)

[email protected]@localhost > select a from _tmp where a is not null;
+---------------------+
| a                   |
+---------------------+
| 0000-00-00 00:00:00 |
+---------------------+
1 row in set (0.00 sec)

Viz: http://bugs.mysql.com/bug.php?id=94

Toto je klasifikováno jako „není chyba“. Navrhují řešení: použijte přísný režim, který převede upozornění na vložení na chybu.

Ačkoli to všechno řekl, to samo o sobě nemůže vysvětlit divokou variabilitu ve výsledcích, které dosahujete (součet is null a is not null počet by měl překročit neomezený počet) ...

6
araqnid

@ypercube:

Nedávno jsem se zeptal, jestli jsem si myslel, že regresní chyba "SELECT COUNT (DISTINCT) havaruje InnoDB, když je operand v primárním klíči nebo jedinečný index", může být v jeho kořeni.

Zde je moje odpověď (původně zde):

http://www.chriscalender.com/?p=315&cpage=1#comment-146

Nemyslím si, že se jedná o stejnou chybu. Tato chyba je více o selhání a vyžaduje specificky SELECT COUNT (DISTINCT) plus operand WHERE je v primárním klíči nebo jedinečném indexu.

Vaše chyba/problém nemá DISTINCT, nerozpadá se a index ve sloupci datetime není primární klíč ani jedinečný. Nicméně, je to trochu podivné z manžety, tak jsem udělal nějaké vyhledávání ačkoli, a běžel přes tuto chybu, která se zdá být více pravděpodobně zapojen/související:

http://bugs.mysql.com/bug.php?id=60105

Ve skutečnosti je označen jako „není chyba“, ale ukazuje/popisuje, jak se můžete dostat do podivného chování, když máte data/datetimes s '0000-00-00' a pomocí IS= NULL a IS NENÍ NULL.

Zajímalo by mě, jestli máte některý z těchto '0000-00-00' řádků, které by mohly mít vliv na počet?

Všimněte si, že Dev, který komentuje zprávu o chybě, zmiňuje také tuto stránku:

Pokud tomu tak není, určitě doporučuji upgradovat a vyzkoušet to na nejnovějších 5.5, což je 5.5.21 (k 2. 2. 2012), protože to bylo 9 měsíců (a 9 vydání) od 5.5.12 byl vydán.

Mějte na paměti, že byste měli být schopni vypsat tabulku (a data) a importovat ji do jiné testovací instance, pouze ji otestovat. Tímto způsobem neovlivníte produkční stroj a můžete si nechat nastavit testovací instanci během několika minut.

Pokud by to přesto ještě nezměnilo, měli byste být schopni vyzkoušet některé další položky, například převést tabulku na MyISAM a zjistit, zda se jedná o globální problém, nebo jen o specifický problém pro InnoDB.

Nebo jsem si všiml, že index dne „odhad_datum“ byl:

KEY estimated_date_index (estimated_date) POUŽITÍ BTREE

Všimněte si „POUŽÍVÁNÍ BTREE“. Možná to zkuste bez POUŽITÍ BTREE a zjistěte, zda stále vidíte stejné chování. (Nebo odeberte index úplně jen pro testování .. to vše pomůže zúžit problém).

Snad to pomůže.

3
Chris Calender

Vidím něco zajímavého v rozvržení tabulky, které volá po „nemám chuť počítat“. To, co chci říct, je jen hrst.

Tento dotaz jste již dříve spustili

select distinct date(estimated_date) from s_p;

Spustit jako COUNT/GROUP BY

select count(1) rowcount,date(estimated_date) from s_p group by date(estimated_date);

Shold získat konečné počty, které jste hledali.

Proč by se však počty pro NULL a NE NULL počítaly správně? Opět je to jen vzdělaný odhad.

Máte sloupec estimated_date indexováno. Zde je to, co chci, abyste vyzkoušeli:

SHOW INDEX FROM s_p;
SHOW INDEX FROM s_p;
SHOW INDEX FROM s_p;
SHOW INDEX FROM s_p;

To není překlep. Chci, abys spustil SHOW INDEX FROM s_p; čtyřikrát (4) krát. Podívejte se na sloupec Cardinality. Od tabulky s_p v InnoDB očekávám, že sloupec kardinality bude pokaždé jiný. Proč?

InnoDB získává hodnotu kardinality odhadem (NO PUN INTENDED) počítáním prostřednictvím položek BTREE. Zkontrolujte systémovou proměnnou innodb_stats_on_metadata . To by mělo být povoleno. Pokud je již povolena, deaktivujte ji a znovu spusťte původní dotazy, abyste zjistili, zda věci vylepšují. TUTO POUZE jako POSLEDNÍ RESORT !!!

Takže místo těchto dotazů:

select count(*) from s_p where estimated_date is null;
select count(*) from s_p where estimated_date is not null;

Snaž se

select count(estimated_date) from s_p;

To by vám mělo poskytnout počet řádků s nenulovým odhadovaným datem.

Další přístup, který byste mohli chtít experimentovat s tímto dotazem na hrubou sílu pomocí funkce ISNULL :

select count(*) rowcount,isnull(estimated_date) IsItNull
from s_p group by isnull(estimated_date);

Doufám, že tyto návrhy pomohou !!!

1
RolandoMySQLDBA

Zkuste dotaz

select * from s_p where estimated_date is null and estimated_date is not null limit 5;
1
Naveen Kumar