2012-02-02 2 views
1

J'ai une assez grande table (plusieurs milliers d'enregistrements) et je ne veux pas m'assurer que les doublons ne peuvent pas être créés le même jour.Laquelle de ces approches SQL est optimale?

N'importe quel gourou SQL là-bas sait laquelle de ces approches est optimale et, si oui, pourriez-vous expliquer pourquoi?

{ created at is a DATETIME column } 
SELECT `records`.* 
FROM `records` 
WHERE DATE(records.created_at) = '2012-02-02'; 

SELECT `records`.* 
FROM `records` 
WHERE records.created_at BETWEEN '2012-02-02 00:00:00' AND '2012-02-02 23:59:59'; 
+0

Quel SGBD? MySQL? –

+0

Désolé, oui MySQL – bodacious

+0

Si vous utilisiez PostgreSQL, vous pourriez utiliser [contraintes d'exclusion] (http://www.postgresql.org/docs/9.0/static/sql-createtable.html#SQL-CREATETABLE-EXCLUDE) pour faire ceci directement. (Edit: désolé, je suis arrivé après la mise à jour). –

Répondre

1

si la comparaison approche, la seconde est certainement meilleure. dans la première variante DATE (somefield) empêche l'optimiseur d'utiliser n'importe quel index. Donc, dans la première variante - mysql va scanner toute la table.

BTW: ils ne sont pas des requêtes égales. Le premier sélectionne seulement '02 -02-2012 ', le deuxième sélectionne 2 et 3 feb.

Mais. les deux variantes ne sont pas appropriées, si vous avez juste besoin d'éviter les doublons. Utilisez un index unique pour cela.

+0

Un index unique sur une colonne datetime empêcherait la création de deux enregistrements dans la même seconde. Cela n'empêcherait pas la création de deux enregistrements par seconde, car ils auraient des dates différentes. – cHao

+0

Merci pour les commentaires - la date dans la deuxième approche était une faute de frappe que je vais corriger pour éviter toute confusion supplémentaire. Je ne savais pas que les fonctions empêchaient l'optimiseur d'utiliser l'index - c'est une connaissance très utile. J'ai un drôle de sentiment que le client va changer le cutoff pour un "jour" (4h du matin à 3h59 du matin) par exemple alors je suis allé avec la 2ème option car elle me protègera de cette éventualité. – bodacious

2

Cela ressemble MySQL (pas mon fort) donc je pourrais être parler tout à fait absurde, mais je regarderais en

  • Création d'une colonne calculée create_at_date comme DATE
  • Ajouter un index unique sur la colonne calculée.

Quelque chose comme

CREATE TABLE records (
    created_at DATETIME 
    , created_at_date AS DATE(created_at) 
    , ... 
) 

CREATE UNIQUE INDEX UIX_RECORDS_CREATED_AT_DATE ON Records (created_at_date) 
+0

merci pour le conseil – bodacious

+0

@bodacious - pas de problème mais je suis curieux de savoir pourquoi vous préférez une méthode ** pas ** appliquée par votre SGBD. –

+0

J'ai essayé de contraindre le DB autant que possible mais le client semble changer d'avis sur un coup de tête alors j'ai permis cette possibilité avec des vérifications de validation au niveau de l'application pour le moment - une fois les décisions finalisées, j'essaierai pour ajouter plus de contraintes sur la base de données – bodacious

0

Le second est moins susceptible de déclencher un balayage de table (en supposant, bien sûr, que vous avez indexé created_at).

Chaque fois que vous effectuez des opérations dans une colonne avant de les vérifier (à moins que le serveur ne soit assez intelligent pour réaliser que cela n'est pas le cas, ce qui n'est pas souvent le cas), valeur avant le test. Signification chaque ligne de la table doit être vérifiée. Si vous avez un index sur created_at, le serveur peut très bien l'ignorer.

+0

Merci pour l'astuce sur l'analyse de la table - J'ai indexé créé à – bodacious

Questions connexes