我们假设数据库很大。我对搜索结果页面有一个非常复杂的查询。在下面的查询中,您可以看到我从user_profile表中检索了一些属性值ids,例如,education是一个属性。当我有属性教育的值id时,我从数组(php代码)中检索此id的标签名称,其中id是数组键。
public static $education = array(0 => 'No answer',
1 => 'High school',
2 => 'Some college',
3 => 'In college',
4 => 'College graduate',
5 => 'Grad / professional school',
6 => 'Post grad');
类似于大约10个其他属性。否则我的查询会更复杂,我需要创建表attribute_id_label并为每个属性创建另一个连接以检索每个属性的值id的标签名称。这意味着额外的10个连接可能会减慢查询速度。但这仍然是正确的方法。
所以我的问题是: 如果table attribute_id_label只有大约500条记录。因为桌子很小,10个加入这个表会有什么大不同吗?即使表user_profile非常大并且查询已经非常复杂,如您所见?
这是我的疑问:
SELECT
group_concat(DISTINCT looking.looking_for SEPARATOR ',') as lookingFor,
group_concat(DISTINCT photo.photo ORDER BY photo.photo_id DESC SEPARATOR ',') as photos,
profile.user_id as userId,
url as profileUrl,
nickname,
avatar.photo,
city,
ethnicity,
education,
occupation,
income,
//and 10 more fields like education, occupation, ethnicity...
FROM user_profile profile
LEFT JOIN user_profile_photo photo ON photo.user_id=profile.user_id
LEFT JOIN user_profile_photo avatar ON avatar.photo_id=profile.photo_id
INNER JOIN user_profile_looking_for looking ON looking.user_id=profile.user_id
LEFT JOIN user_profile_txt txt ON txt.user_id = profile.user_id
INNER JOIN place a ON a.place_id=profile.place_id
INNER JOIN (SELECT lat, lon FROM place WHERE place_id = :place_id) b ON (3959 * acos( cos( radians(b.lat) ) * cos( radians( a.lat ) ) * cos( radians( a.lon ) - radians(b.lon) ) + sin( radians(b.lat) ) * sin( radians( a.lat ) ) ) ) < :within
GROUP BY profile.user_id LIMIT 0,12
大多数属性都不会被用户填充,因为您建议使用非NULLable,那么对于那些未填充的属性最好使用哪些属性?我可以使用每个属性额外的字段没有答案。每个属性都有额外的值无答案。让我们给出属性教育和想要的例子。属性教育有id 1,想要是2.
eav_attribute_option
option_id | attr_id | label
1 | 1 | No answer
2 | 1 | High school
3 | 1 | ...
4 | 2 | No answer
5 | 2 | Opportunities
6 | 2 | ...
但现在重复出现问题每个属性没有回答值。但这是避免NULL值的方法。我不确定这是否正确。
答案 0 :(得分:1)
我做了很多这样的代码清单工作。它通常有助于提高性能而不是伤害。 @alxklx指出了事实:你必须确保你的代码表(例如教育)形式良好。也就是说,
int
而不是decimal
或varchar
。如果你做这些事情,你的JOIN可以看起来很简单
FROM people p
JOIN education e ON p.education_id = e.education_id
并且RDBMS的优化器知道它们是简单的1:1连接。
所有这些,在将其置于实时系统之前,需要检查任何复杂查询的功能和性能。
如果您的people
中缺少数据,请使用0或1的education_id(或其他一些attribute_id)。在每个代码列表表中添加一行,其中id为0或1,值为“unknown”或“user not not告诉我们”或任何有意义的行。 (您可以根据应用程序的便利性选择零或一。我更喜欢零,但这只是个人偏好。)
答案 1 :(得分:0)
您需要考虑的两件非常重要的事情 - 首先是表和第二索引有多大。如果大型表上缺少索引,或者该字段的数据类型与表的字段的数据类型不同,则将其加入 - 它可能需要数天甚至数月。就个人而言,我已经用巨大的桌子做了更大的选择,结果非常好,大约2秒钟。使用explain select来查看查询是如何站立的,如果某些内容不正确 - 请描述您的表,显示其索引并进行比较。如果我们不了解您的数据库设计,那么很难给出明确的答案......
答案 2 :(得分:0)
一般而言 - 非常非常通用 - 加入外键关系 - 即attribute_id确实是主键,具有相应的索引,具有像INT这样的索引友好数据类型,您可以有效地处理连接从性能的角度来看是免费的。
最好的方法是尝试一下,然后让EXPLAIN告诉你发生了什么。