mardi 26 mai 2009

2 managers ndb_mgmd dans une config MySQL Cluster

Lorsque l'on modifie des paramètres de mémoire ou autres qui ne nécessitent pas de recréer le cluster, contrairement au nombre de noeuds pour les versions du moteur NDB < 7.0, il est nécessaire de faire un Rolling Restart. Cependant, dans le cas d'une configuration à plusieurs managers il est nécessaire de tous les arrêter au même moment. Ceci est dû au fait que tant qu'un manager est actif c'est sa configuration qui prime. L'impact est que le redémarrage tour à tour des managers entraînera la conservation de l'ancienne configuration de départ, ce qui n'est pas le résultat attendu.

mardi 12 mai 2009

Index et valeurs nulles

Une différence importante entre MySQL et Oracle est l'indexation. En effet, Oracle n'indexe pas les données entièrement nulles. Par entièrement cela signifie que si vous indexez 2 colonnes, le couple null ne sera pas stocké dans l'index et cela a son importance !

Par exemple, si nous utilisons le schema SCOTT pour tenter d'utiliser un index sur une colonne pouvant être nulle :

SQL> select * from emp;

EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO
---------- ---------- --------- ---------- --------- ---------- ---------- ----------
7369 SMITH CLERK 7902 17-DEC-80 800 20
7499 ALLEN SALESMAN 7698 20-FEB-81 1600 300 30
7521 WARD SALESMAN 7698 22-FEB-81 1250 500 30
7566 JONES MANAGER 7839 02-APR-81 2975 20
7654 MARTIN SALESMAN 7698 28-SEP-81 1250 1400 30
7698 BLAKE MANAGER 7839 01-MAY-81 2850 30
7782 CLARK MANAGER 7839 09-JUN-81 2450 10
7788 SCOTT ANALYST 7566 19-APR-87 3000 20
7839 KING PRESIDENT 17-NOV-81 5000 10
7844 TURNER SALESMAN 7698 08-SEP-81 1500 0 30
7876 ADAMS CLERK 7788 23-MAY-87 1100 20
7900 JAMES CLERK 7698 03-DEC-81 950 30
7902 FORD ANALYST 7566 03-DEC-81 3000 20
7934 MILLER CLERK 7782 23-JAN-82 1300 10

14 rows selected.

SQL> create index idx_emp_ename on emp(ename);

Index created.

SQL> set autotrace trace explain
SQL> select 1 from emp where ename is null;

Execution Plan
----------------------------------------------------------
Plan hash value: 3956160932

--------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 7 | 3 (0)| 00:00:01 |
|* 1 | TABLE ACCESS FULL| EMP | 1 | 7 | 3 (0)| 00:00:01 |
--------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

1 - filter("ENAME" IS NULL)


Oracle décide donc d'effectuer un FULL SCAN de la table car la donnée nulle ne pouvant être stockée dans un index il est nécessaire de parcourir la table entièrement. Ce qui n'est pas le cas si on index une colonne supplémentaire non nulle (le couple ne sera dans ce cas jamais nul)

SQL> create index idx_emp_ename_1 on emp(ename,1);

Index created.

SQL> select 1 from emp where ename is null;

Execution Plan
----------------------------------------------------------
Plan hash value: 2365361045

------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 7 | 1 (0)| 00:00:01 |
|* 1 | INDEX RANGE SCAN| IDX_EMP_ENAME_1 | 1 | 7 | 1 (0)| 00:00:01 |
------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

1 - access("ENAME" IS NULL)


On peut donc en déduire l'importance de rajouter la contrainte not null quand vous savez que ce champ ne peut être null. En effet, un count(*) pourra dans ce cas effectuer un INDEX FULL SCAN sachant qu'aucune donnée ne peut être nulle et donc il n'y a aucune entrée qui manque dans l'index.

Contrairement à Oracle, MySQL stocke aussi les valeurs nulles dans ses index comme l'indique la colonne NULL dans la sortie de la commande "SHOW INDEX FROM MATABLE". Ainsi si l'on recherche le nombre d'entrée nulles d'une table, MySQL utilisera l'index disponible :

mysql [localhost] {msandbox} (test) > explain select count(*) from t3 where id is null;
+----+-------------+-------+------+---------------+------+---------+-------+------+--------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+------+---------------+------+---------+-------+------+--------------------------+
| 1 | SIMPLE | t3 | ref | id | id | 5 | const | 100 | Using where; Using index |
+----+-------------+-------+------+---------------+------+---------+-------+------+--------------------------+
1 row in set (0.00 sec)

mysql [localhost] {msandbox} (test) > show index from t3;
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment |
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
| t3 | 1 | id | 1 | id | A | 1 | NULL | NULL | YES | BTREE | |
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
1 row in set (0.00 sec)

De la même manière il est important d'ajouter la contrainte NOT NULL si le champ ne sera jamais nul, ce qui permet à MySQL d'effectuer certaines optimisations et d'économiser un bit par enregistrement.
Blogged with the Flock Browser
Lire la suite...