Question

Je l'ai regardé partout et n'a pas encore trouvé une façon intelligente de gérer cela, mais je me sens sûr que l'on est possible:

Une table de données historiques contient des informations trimestrielles:

CREATE TABLE Quarterly (
unique_ID INT UNSIGNED NOT NULL,
date_posted DATE NOT NULL,
datasource TINYINT UNSIGNED NOT NULL,
data FLOAT NOT NULL,
PRIMARY KEY (unique_ID));

Une autre table de données historiques (ce qui est très grand) contient des informations par jour:

CREATE TABLE Daily (
unique_ID INT UNSIGNED NOT NULL,
date_posted DATE NOT NULL,
datasource TINYINT UNSIGNED NOT NULL,
data FLOAT NOT NULL,
qtr_ID INT UNSIGNED,
PRIMARY KEY (unique_ID));

Le champ qtr_ID ne fait pas partie de l'alimentation des données quotidiennes qui ont peuplé la base de données - à la place, je dois remplir rétroactivement le champ qtr_ID dans le tableau quotidien avec l'ID de ligne Quarterly.unique_ID, en utilisant ce qui aurait été le plus récent données trimestrielles sur Daily.date_posted que pour cette source de données.

Par exemple, si les données trimestrielles est

  

101 2009-03-31 1 4.5
   102 30/06/2009 1 4,4
   103 31.03.2009 2 7,6
   104 2009-06-30 2 7.7
   105 30/09/2009 1 4,7

et les données par jour est

  

1001 14.07.2009 1 3,5 ??
  1002 2009-07-15 1 3.4 &&
  1003 2009-07-14 2 2.3 ^^

alors nous voulons l'?? champ qtr_ID à attribuer « 102 » comme le quartier le plus récent pour cette source de données à cette date, et && serait également « 102 », et ^^ serait « 104 ».

Les défis comprennent que les deux tables (en particulier la table quotidienne) sont en fait très grande, ils ne peuvent pas être normalisées pour se débarrasser des dates répétitives ou optimisées, et pour certaines entrées quotidiennes il n'y a pas d'entrée trimestrielle précédente.

J'ai essayé une variété de jointures, en utilisant datediff (où le défi est de trouver la valeur minimale de datediff supérieure à zéro), et d'autres tentatives, mais rien ne fonctionne pour moi - habituellement ma syntaxe se brise quelque part. Toutes les idées bienvenues - Je vais signer des idées de base ou les concepts et le dos de rapport

.
Était-ce utile?

La solution

Juste pour le sous-requête id trimestre en utilisant quelque chose comme:

(
 SELECT unique_ID 
 FROM Quarterly 
 WHERE 
     datasource = ? 
     AND date_posted >= ? 
 ORDER BY
     unique_ID ASC
 LIMIT 1
)

Bien sûr, cela ne sera probablement pas vous donner les meilleures performances, et il suppose que les dates sont ajoutées Quarterly séquentielle (autrement order by date_posted). Cependant, il devrait résoudre votre problème.

Vous pouvez utiliser cette sous-requête sur vos relevés de INSERT ou UPDATE que la valeur de votre champ qtr_ID pour votre table de Daily.

Autres conseils

Les suivants semble fonctionner exactement comme prévu, mais il est sûrement laid (avec trois appels au même DATEDIFF !!), peut-être en voyant une personne de requête de travail pourrait être en mesure de réduire encore ou l'améliorer:

UPDATE Daily SET qtr_ID = (select unique_ID from Quarterly
WHERE Quarterly.datasource = Daily.datasource AND
DATEDIFF(Daily.date_posted, Quarterly.date_posted) = 
(SELECT MIN(DATEDIFF(Daily.date_posted, Quarterly.date_posted)) from Quarterly
WHERE Quarterly.datasource = Daily.datasource AND
DATEDIFF(Daily.date_posted, Quarterly.date_posted) > 0));

Après plus de travail sur cette question, je me suis retrouvé avec d'énormes améliorations de performance sur le concept original. La plus importante amélioration a été de créer des indices dans les deux tables quotidiennes et trimestrielles - Daily j'ai créé des indices sur (source de données, date_posted) et (date_posted, source de données) UTILISATION BTREE et (source de données) UTILISATION HASH, et trimestriel je l'ai fait la même chose. C'est surpuissant, mais il fait que j'avais une option que le moteur de recherche pourrait utiliser. Cela réduit le temps de requête à moins de 1% de ce qu'il avait été. (!!)

Alors, je l'ai appris que, compte tenu de mes circonstances particulières que je pourrais utiliser MAX () au lieu de ORDER BY et LIMIT donc j'utiliser un appel à MAX () pour obtenir le numéroMsg approprié. Cela réduit le temps de recherche d'environ 20%.

Enfin, je l'ai appris avec le moteur de stockage InnoDB je pouvais segmenter le morceau de la table Daily que je mettais à une requête, ce qui m'a permis de multi-thread les requêtes avec un petit coude-graisse et les scripts. Le traitement parallèle a bien fonctionné et chaque fil a réduit le temps de requête de façon linéaire.

Ainsi, la requête de base qui effectue littéralement 1000 fois mieux que ma première tentative est:

UPDATE Daily
SET qtr_ID =
(
  SELECT MAX(unique_ID)
  FROM Quarterly
  WHERE Daily.datasource = Quarterly.datasource AND
        Daily.date_posted > Quarterly.dateposted
)
WHERE unique_ID > ScriptVarLowerBound AND
      unique_ID <= ScriptVarHigherBound
;
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top