2010-09-16 4 views
2

J'ai besoin d'une requête pour empêcher une jointure qui produit 1.34218E + 35 résultats!Évitez les résultats de jointure de requête intermédiaire énorme (1.33615E + 35 lignes)

J'ai un tableau item (environ 8k articles, par exemple bouclier de Foo, arme de barre), et chaque article est l'un des 9 item_type différents (armure, arme, etc.). Chaque élément a plusieurs entrées dans item_attribute (par exemple Damage, Defense). Voici une représentation pseudo-code:

Table item (
item_id autoincrement, 
... 
item_type_id char, --- e.g. Armor, Weapon, etc 
level int    --- Must be at least this level to wear this item 
); 

Table item_attribute (
item_id int references item(item_id), 
... 
attribute char  --- e.g. Damage, Defense, etc 
amount int   --- e.g. 100 
) 

Maintenant, un personnage porte 9 articles au total à la fois (un chacun armure, arme, bouclier, etc) que j'appelle une configuration . Je veux construire une liste de configurations qui maximise un attribut, mais a un minimum d'un autre attribut. En termes d'exemple: pour un niveau de personnage 100, présente les 10 meilleurs réglages par dégâts où sum(defense of all items) >= 100.

L'approche naïve est:

select top 10 
q1.item_id,q2.item_id,q3.item_id,..., q1.damage+q2.damage+q3.damage... as damage 
from 
(select item_id from item where item_type = 'Armor' 
    and level <= 100) as q1 
inner join (select item_id from item where item_type = 'Shield' 
    and level <= 100) as q2 on 1 = 1 
inner join (select item_id from item where item_type = 'Weapon' 
    and level <= 100) as q3 on 1 = 1 
... 
where 
q1.defense+q2.defense+q3.defense+... >= 100 
order by 
q1.damage+q2.damage+q3.damage,... descending 

Mais, parce qu'il ya environ 8k articles dans item, cela signifie que l'importance des résultats pour le SGBD pour trier par près de 8000^9 = 1.34218E + 35 différentes configurations! Y a-t-il un meilleur moyen? Vous ne pouvez pas vous joindre uniquement aux # éléments les plus puissants?

+3

Êtes-vous un développeur de World of Warcraft ou quelque chose? 8k articles! OMFG –

+0

Cela pourrait-il être une tâche que le joueur devrait faire (en optimisant sa tenue selon vos règles)? Ils résolvent le problème comme ils le veulent; vous faites simplement respecter les règles. – John

+0

8k articles n'est pas si difficile à acquérir. C'est moins de 900 éléments par type, dont beaucoup ont probablement été générés par programmation. – corsiKa

Répondre

1

Je pense que votre problème peut être résolu en utilisant integer linear programming. Je suggère de retirer vos données de la base de données et de les donner à l'un des solveurs hautement optimisés qui ont été écrits par des personnes qui ont travaillé longtemps sur leurs algorithmes, plutôt que d'essayer d'écrire votre propre solveur en SQL.

+0

La programmation linéaire en nombre peut fournir une solution plus rapide à la requête ci-dessus en traduisant le problème en un programme "optimisé" pour le résoudre. Mais, à moins de manquer quelque chose (car je ne comprends pas la programmation linéaire en nombres entiers), cela ne réduit pas la complexité ou ne répète pas le problème dans des termes plus simples à résoudre. –

+0

@Derek Frye: Je serais surpris si vous ou quelqu'un d'autre ici pouvez écrire une solution de travail pour cela en SQL. S'ils le font, ils recevront certainement mon upvote. Mais il me semble que SQL est le mauvais outil pour résoudre ce problème. La complexité temporelle du problème n'est pas améliorée en utilisant un meilleur outil - il est NP-Hard de toute façon, mais ce n'est pas une raison pour éviter d'utiliser le bon outil. Vous pouvez marteler dans un clou en utilisant un marteau dans le temps constant. Vous pouvez également marteler dans un clou en utilisant un tournevis à temps constant. Mais cela ne signifie pas que les outils sont également bons pour la tâche. –

+0

Vous avez raison, il semble qu'il n'y ait personne avec une solution qui réduit la complexité du problème. Probablement traduire cela en une sorte de solveur optimisé est la meilleure façon de faire. –

0

Devrait réduire la taille de la collection de manière drastique. Logiquement, la somme des éléments les plus élevés devrait fournir les combinaisons les plus élevées.

+0

Étant donné que les attributs d'élément ne sont pas augmentés de façon monotone avec le niveau, la solution proposée présente la faille que la "meilleure" configuration est inférieure au nombre spécifié d'éléments à renvoyer ... –

0

La première chose que je ferais est d'isoler vos articles. Au lieu de regarder la configuration dans son ensemble, regardez la somme des éléments individuels. À moins que vos objets n'interagissent l'un avec l'autre (bonus d'ensemble) vous allez faire un long chemin en maximisant stat A et en minimisant la stat B pour un seul slot, et en répétant ce processus pour chaque slot d'élément dans votre configuration. Cela réduira drastiquement la complexité de la requête, même si cela impliquera plus de requêtes. Cela devrait accélérer les choses à long terme. Une autre chose à se demander est combien vaut-il la peine de gagner la stat B (celle que vous voulez perdre) pour gagner stat A? Si vous pouviez gagner 1000 A, et ne gagner que 1 B, cela pourrait en valoir la peine. Mais, qu'en est-il de gagner 10 A, mais il faudrait gagner 9 B pour le faire? Maintenant les choses changent un peu.

Si vous respectez un ratio A: B, vous pouvez probablement faire chaque slot séparément, et joindre chacun de ces résultats séparés en une seule requête.

Questions connexes