2016-12-23 1 views
0

J'ai une énorme quantité de données provenant d'une source et chaque enregistrement a une dimension dim1. Dim1 peut avoir jusqu'à 1 million de valeurs uniques. Certains d'entre eux auront beaucoup de données et d'autres auront moins. Par exemple Dim1value1 peut avoir des enregistrements 100K, Dim1value2 peut contenir 1 million d'enregistrements, Dim1value3 peut avoir 10 enregistrements et ainsi de suite.Partition de données en 20 partitions à peu près égales dans SQL Server

Maintenant, je veux les regrouper en partitions quelque peu égales de sorte que les données relatives à chaque Dim1 vont dans un groupe et je veux créer environ 20 groupe un peu égal.

Fondamentalement, chaque enregistrement ayant Dim1Value1 devrait aller dans un groupe et ainsi de suite. Voici un script qui montre comment ntile ne le fait pas.

IF OBJECT_ID('tempdb.dbo.#t') IS NOT NULL 
    DROP TABLE #t 

CREATE TABLE #t 
(
    Dim1 varchar(100), 
    numberofrecs int 
) 

DECLARE @counter int = 1 

WHILE(@counter < = 100) 
BEGIN 
    INSERT #t 
     SELECT 
      'Dim1value' + CAST(@counter AS VARCHAR(10)), 
      CAST(RAND() * 100 AS INT) 

    SET @counter = @counter + 1 
END 

SELECT * FROM #t 

SELECT 
    NTILE(5) OVER(order by numberofrecs), 
    Dim1, * 
FROM #t 
+0

Est-ce mysql ou sql-server? mettre à jour les tags et conserver uniquement le fournisseur concerné. – Dekel

+0

Si SQL Server considère NTile() https://msdn.microsoft.com/en-us/library/ms175126.aspx –

+0

Je ne pense pas que Ntile le fera. Je l'ai considéré mais il ne fait que trie la mesure et divise ensuite ma dimension en un nombre de groupes. Fondamentalement, il mettra toutes les dimensions qui ont le plus grand nombre dans le même groupe. ce n'est pas ce que je veux ... ce script sql va le démonoser ... –

Répondre

0

La meilleure façon de diviser votre dim1 serait:

SELECT ROWNUMBER() OVER (par ordre numberofrecs)% 20 + 1 AS partnr, Dim1, * DE #t ORDER BY Ceci n'est pas un algorithme parfait, il faudra juste approximer les groupes en les classant par le nombre d'enregistrements et la pseudo-partition en utilisant la fonction modulo. Pour un meilleur algorithme, il serait logique d'implémenter une procédure stockée CLR en utilisant la logique orientée objet au lieu de l'approche relationnelle. Une autre façon serait d'avoir un processus ETL analyser vos données et choisir la bonne partition.

Je crois que vous avez mal compris le concept de partitionnement. Bien que vous deviez choisir le cluster de votre partition, en essayant de répartir autant que possible les données sur les partitions, la quantité de partitions n'est pas une valeur constante dans un environnement réel. Le but du partitionnement est d'optimiser le stockage de données, le dml et l'interrogation. Vous pourriez également vouloir mettre en place une fenêtre coulissante, mais ce serait vraiment complexe et non intuitif avec votre approche. Les données de votre dim1 sont-elles fixes et inaltérables? Si oui, vous pouvez choisir votre approche envisagée. Sinon, vous devez trouver un index qui s'adapte au clustering dans les partitions. Par exemple, une valeur de date pourrait être un candidat et diviser cette date en semaines, mois ou années ou plus.

+0

J'ai fait quelque chose de similaire. Mon problème est que je vais presque TOUJOURS interroger à partir d'une valeur de Dim1. Et je ne veux pas frapper plusieurs partitions pour cela. Et quand je demande une valeur particulière de Dim1, je vais interroger beaucoup d'histoire, donc le partitionnement par jour ou par semaine n'a pas de sens. Si je fais une partition muette par juste valeur de Dim1, par exemple. Dim1value1 à value100 va dans 1, la valeur de 101 à 200 va dans 2 et ainsi de suite, je finirai avec des partitions inégales ... comme Dim1value1 pourrait avoir plus de nombre d'enregistrements si vous ajoutez dim1value2 à value200 tous ensemble ... –