Mysql : comment reinitialiser l'auto-increment d'une table ?

Bonjour,

j’ai une table nommé produit, où la 1er colonne nommé id_produit est de type SMALLINT, en auto-increment, et primary.

Lorsque je supprime des vielles lignes dans cette table, la colonne id_produit présente maintenant ces valeurs :

id_produit
-----------
2
3
4
6
7
8
...

Donc la j’ai supprimé les ligne 1 et 5.

Maintenant, je voudrais savoir s’il est possible par une requête de reinitialiser l’auto-incrément de cette colonne, càd que : 2 devient 1, 3 devient 2, 4 devient 3, 6 devient 4, 7 devient 5, 8 devient 6 pour avoir à la fin :

id_produit
-----------
1
2
3
4
5
6
...

Alors, pourquoi j’ai besoin de faire ça ? parce que la colonne est de type smallint (qui va de -32 768 à 32 767)
, et comme je met régulièrement à jour les données de la table en supprimant et en ajoutant des lignes, je ne voudrais pas insérer des lignes avec un id_produit supérieur à ce qui est autorisé (càd limité à 32 767).
Je ne voudrais pas utiliser le type MEDIUMINT (de -8 388 608 à 8 388 607) parce que je n’ai que 25.000 produits seulement à mettre à jour dans ma table, donc pas besoin de consommer inutilement la mémoire et ralentir bêtement avec MEDIUMINT.

Merci d’avance, cordialement.

Et mettre à jour tous les enregistrements des autres tables qui pointent sur ces produits…

Rien que la renumérotation régulière de tes produits va consommer énormément plus de ressources que si tu utilisais une clé primaire adaptée (INT voire BIGINT), sans même parler de la mise à jour des enregistrements liés. Tu prends le problème par le mauvais bout l’ami… Même une clé primaire BIGINT n’affectera en rien tes performances ou l’espace utilisé (moins de 32K produits = moins de (32K * 8 = 256K) utilisés pour stocker les données de ta clé primaire).

Là tu nous sors un cas d’école de micro-optimisation qui (1) n’a pas lieu d’être et (2) a l’effet exactement inverse de ce que tu souhaites. :wink:
Je pensais pourtant que le « bug de l’an 2000 » (pour rappel : codage des années sur 2 chiffres seulement) avait fait prendre conscience aux gens des dangers de ce genre de choses.

Merci syam.

=>Dans mon cas la table produit est la seule de ma base de données.

=>Je retiens.

Maintenant, j’ai un autre problème dans une autre base de données. Cette base de données n’a qu’une seule table nommé product, et qui contient plus de 800.000 produits. Voici sa structure :

mysql > describe product;
+-----------------------+---------------+------+-----+---------+----------------+
| Field                 | Type          | Null | Key | Default | Extra          |
+-----------------------+---------------+------+-----+---------+----------------+
| id_product            | mediumint(6)  | NO   | PRI | NULL    | auto_increment |
| id_product_file       | varchar(20)   | YES  |     | NULL    |                |
| id_annonceur          | smallint(6)   | YES  |     | NULL    |                |
| name                  | varchar(500)  | YES  |     | NULL    |                |
| mots_cles             | varchar(500)  | YES  |     | NULL    |                |
| description           | varchar(1500) | YES  |     | NULL    |                |
| url_image             | varchar(300)  | YES  |     | NULL    |                |
| extension_image       | varchar(6)    | YES  |     | NULL    |                |
| price                 | float         | YES  |     | NULL    |                |
| price_avant_reduction | float         | YES  |     | NULL    |                |
| url_tracking          | varchar(500)  | YES  |     | NULL    |                |
| status                | varchar(15)   | YES  |     | NULL    |                |
+-----------------------+---------------+------+-----+---------+----------------+
12 rows in set (0.05 sec)

Mon problème est qu’une simple requête select me fait exploser le CPU (+400% de mon CPU), alors que ma requête
est juste :

$query = "select name from product where mots_cles like '%".$_POST[mots_cles]."%'";

Est-ce que c’est parce que j’ai trop de données dans ma table (+800.000) ? Comment rendre rapide le retournement des résultats (pourtant dans my.cnf, j’ai doublé les paramètres des caches).

Mon CPU est un modèle récent, un intel core i3.

[quote=“fluo”]une simple requête select me fait exploser le CPU (+400% de mon CPU), alors que ma requête
est juste :

$query = "select name from product where mots_cles like '%".$_POST[mots_cles]."%'"; [/quote]
Ce n’est pas une “simple” requête : tu cherches des informations à l’intérieur d’un champ, ce qui oblige MySQL à passer tous les enregistrements en revue un par un. Normal que ça rame.

Deux solutions :

  • la bonne, mettre les mots-clés dans une table séparée et faire une troisième table de liaison mots-clés <=> produits. Tu te retrouveras avec une requête JOIN sur les 3 tables et un WHERE … IN(‘mot1’, ‘mot2’, …)
  • la mauvaise, mettre ta colonne mots_cles en index full-text ce qui devrait accélérer les choses (sans garanties, je n’utilise pas donc je parle en théorie). Mais ce n’est pas la bonne manière de faire : un champ SQL est fait pour contenir une information, si tu as plusieurs informations (en l’occurrence une liste de mots-clés) dans un seul champ c’est qu’il te manque des tables.

De manière générale, quand tu as des énormes problèmes de performance comme ça, commence par te demander quels index ta requête utilise.

Oh, et au passage, tu as un trou de sécurité (injection SQL) dans ta requête. :mrgreen:

[quote=“fluo”]Deux solutions :

  • la bonne, mettre les mots-clés dans une table séparée et faire une troisième table de liaison mots-clés <=> produits. Tu te retrouveras avec une requête JOIN sur les 3 tables et un WHERE … IN(‘mot1’, ‘mot2’, …)
  • la mauvaise, mettre ta colonne mots_cles en index full-text ce qui devrait accélérer les choses (sans garanties, je n’utilise pas donc je parle en théorie). Mais ce n’est pas la bonne manière de faire : un champ SQL est fait pour contenir une information, si tu as plusieurs informations (en l’occurrence une liste de mots-clés) dans un seul champ c’est qu’il te manque des tables.
    [/quote]
    =>je pense qu’une table mots_cles séparée et une jointure avec la table principale est la meilleure solution.

=> merci, c’est juste pour simplifier la description du problème.