我的数据库存储游戏中的项目列表及其相关信息。
主要项目表包含所有只能包含单个条目的字段,例如权重,简短描述等。
可以是一组值的字段由具有2个字段,项目ID和属性ID的表格表示,例如允许使用该项目的种族列表或可以佩戴该项目的地点列表。在联接中导致大量额外行的那个是与项目关联的影响列表和影响的值(例如:影响allowed_carrying_weight 10或影响生命值20或两者都不影响)。
以编程方式,其中一些通过使用位域存储在1个字段中,例如每个种族获得一个数字,如果允许种族使用该项目,则将设置AllowedRaceInteger & 2^(raceNumber)
。
例如,背包可能被握在手中或戴在背上。也许这个特殊的背包可能只供人类和精灵使用。
SELECT DISTINCT i.id, iwt.wearlocID, i.sdesc, i.wearProg, i.isOOG, i.minLvl, i.maxLvl,
iaft.affectID, iaft.amount, NULL AS affectbyID FROM item i
INNER JOIN itemwearTable iwt ON i.id=iwt.itemID
LEFT JOIN itemaffectTable iaft ON i.id=iaft.itemID
WHERE iwt.wearlocID >= 1 AND iwt.wearlocID <= 22 AND i.minlvl <= 50
UNION
SELECT DISTINCT i.id, iwt.wearlocID, i.sdesc, i.wearProg, i.isOOG, i.minLvl, i.maxLvl,
NULL AS affectID, NULL AS amount, iafbt.affectbyID FROM item i
INNER JOIN itemwearTable iwt ON i.id=iwt.itemID
LEFT JOIN itemaffectedbyTable iafbt ON i.id=iafbt.itemID
WHERE iwt.wearlocID >= 1 AND iwt.wearlocID <= 22 AND i.minlvl <= 50
ORDER BY wearlocID, sdesc,id
即使在非常小的数据集上,此查询也可能需要7-10秒才能执行。我设置的唯一索引是item.id.我可以使用什么标准来决定是否应该对事件编制索引?例如,我的表中将项目与值相关联的所有值都应编入索引,否则会产生新问题?
这可以通过某种方式用位域编码简化吗?我不认为它可以,因为它需要查询select * from somewhere.field&amp; 256 == 1 ..
由于
答案 0 :(得分:1)
数据库优化
至少,值得在itemId
,itemwearTable
和itemaffectTable
的{{1}}上添加索引。索引外键几乎总是一个好主意。
我在此查询中看到的索引的唯一其他候选者是wearlocID。但是,索引是否会产生影响将取决于该列的基数(即该列可包含多少个不同的值)。
查询优化
如果可以预期第一个和第二个查询会返回不同的结果,那么使用itemaffectedbyTable
而不是UNION ALL
可能会带来一些好处。 UNION
消除了重复,这往往会导致查询被排序,这更加昂贵。
您似乎运行相同的基本查询两次,但最终连接存在差异。您可能会受益于使用公用表表达式(CTE)。这允许您运行一次查询并多次引用结果。
实现这两个建议看起来像这样:
UNION
其他笔记
您似乎从此查询中的每个表中获取每一行。这是一个真实的用例吗?如果没有尝试使用更接近您实际期望的应用程序运行的查询(例如,如果它将一次为一个项运行此查询)。通常,尝试从每个表中获取每一行的效果与更有针对性的查询不同。