我有一个奇怪的数据库问题,我无法做头和尾巴,我希望这个聪明的蜂巢头脑可以帮助我。简而言之,我发现尽管格式相同,但对我的数据库的一些查询速度非常慢,而其他查询几乎是即时的。例如,这个查询:
func pickerView(_ pickerView: UIPickerView, viewForRow row: Int, forComponent component: Int, reusing view: UIView?) -> UIView {
let pickerLabel = UILabel()
pickerLabel.attributedText = NSAttributedString(string: capicityArray[row], attributes: attributes: [NSAttributedStringKey.font:GlobalFont.Font_GillSansStd(fontsize: 22), NSAttributedStringKey.foregroundColor: GlobalColor.Color153])
pickerLabel.isOpaque = true
pickerLabel.textAlignment = .center
return pickerLabel
}
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
self.applySelection(pickerView: pickerView, row: row, component: component)
}
以0.06秒的形式返回结果。超过我的需求足够快。但此查询:
SELECT SQL_NO_CACHE DISTINCT pr.Master_Person_ID
FROM liverpool.person_record pr
JOIN liverpool.person_property_view ppv1 ON (pr.Master_Person_ID = ppv1.Master_Person_ID)
JOIN liverpool.property_type_class ptc1 ON (ptc1.Property_ID = ppv1.Property_ID)
JOIN liverpool.person_property_view ppv2 ON (pr.Master_Person_ID = ppv2.Master_Person_ID)
JOIN liverpool.property_type_class ptc2 ON (ptc2.Property_ID = ppv2.Property_ID)
WHERE ptc1.Property_Class_ID = 2
AND ppv1.Property_Value = 'Ruth'
AND ptc2.Property_Class_ID = 6
AND ppv2.Property_Value = 'Davies'
ORDER BY pr.Year_From_Origin_Record, pr.Recorded_Date
LIMIT 100000;
这里唯一的区别在于搜索参数。但是第二个查询执行时间超过 9分钟。如果使用" LIKE"而不是" ="。当然还有更多的爱德华'在我的数据库中,而不是露丝的,'但当然,单凭这个问题并不能解释为什么第二个查询比第一个查询慢几个数量级?您可以看到,查询使用自联接。我很欣赏这些可能不是最有效的方法,但它们可以满足我的需求并使我的前端代码更简单。大多数时候,他们工作正常。
这是第一个(快速)查询的EXPLAIN:
SELECT SQL_NO_CACHE DISTINCT pr.Master_Person_ID
FROM liverpool.person_record pr
JOIN liverpool.person_property_view ppv1 ON (pr.Master_Person_ID = ppv1.Master_Person_ID)
JOIN liverpool.property_type_class ptc1 ON (ptc1.Property_ID = ppv1.Property_ID)
JOIN liverpool.person_property_view ppv2 ON (pr.Master_Person_ID = ppv2.Master_Person_ID)
JOIN liverpool.property_type_class ptc2 ON (ptc2.Property_ID = ppv2.Property_ID)
WHERE ptc1.Property_Class_ID = 2
AND ppv1.Property_Value = 'Edward'
AND ptc2.Property_Class_ID = 6
AND ppv2.Property_Value = 'Abbott'
ORDER BY pr.Year_From_Origin_Record, pr.Recorded_Date
LIMIT 100000;
这是第二个(慢)查询的EXPLAIN:
id,select_type,table,partitions,type,possible_keys,key,key_len,ref,rows,filtered,Extra
1,SIMPLE,ptc1,NULL,ref,"PRIMARY,Property_ID_IDX,Property_Class_ID_IDX",Property_Class_ID_IDX,4,const,2,100.00,"Using index; Using temporary; Using filesort"
1,SIMPLE,pt,NULL,eq_ref,PRIMARY,PRIMARY,4,liverpool.ptc1.Property_ID,1,100.00,NULL
1,SIMPLE,rlt,NULL,eq_ref,PRIMARY,PRIMARY,4,liverpool.pt.Record_Link_Type_ID,1,100.00,"Using where; Using index"
1,SIMPLE,prp,NULL,ref,"PRIMARY,Property_Value_IDX,Person_Record_ID_IDX",Property_Value_IDX,23,"const,liverpool.ptc1.Property_ID",13,100.00,"Using where"
1,SIMPLE,pr,NULL,eq_ref,"PRIMARY,Master_Person_ID_IDX,Person_Record_ID_IDX",PRIMARY,4,liverpool.prp.Person_Record_ID,1,100.00,"Using where"
1,SIMPLE,rt,NULL,eq_ref,"PRIMARY,Record_Type_ID",PRIMARY,4,liverpool.pr.Record_Type_ID,1,100.00,"Using index"
1,SIMPLE,pr,NULL,ref,Master_Person_ID_IDX,Master_Person_ID_IDX,17,liverpool.pr.Master_Person_ID,1,100.00,NULL
1,SIMPLE,pr,NULL,ref,"PRIMARY,Master_Person_ID_IDX,Person_Record_ID_IDX",Master_Person_ID_IDX,17,liverpool.pr.Master_Person_ID,1,100.00,Distinct
1,SIMPLE,rt,NULL,eq_ref,"PRIMARY,Record_Type_ID",PRIMARY,4,liverpool.pr.Record_Type_ID,1,100.00,"Using index; Distinct"
1,SIMPLE,ptc2,NULL,ref,"PRIMARY,Property_ID_IDX,Property_Class_ID_IDX",Property_Class_ID_IDX,4,const,5,100.00,"Using index; Distinct"
1,SIMPLE,pt,NULL,eq_ref,PRIMARY,PRIMARY,4,liverpool.ptc2.Property_ID,1,100.00,Distinct
1,SIMPLE,rlt,NULL,eq_ref,PRIMARY,PRIMARY,4,liverpool.pt.Record_Link_Type_ID,1,100.00,"Using where; Using index; Distinct"
1,SIMPLE,prp,NULL,eq_ref,"PRIMARY,Property_Value_IDX,Person_Record_ID_IDX",PRIMARY,8,"liverpool.ptc2.Property_ID,liverpool.pr.Person_Record_ID",1,5.00,"Using where; Distinct"
我知道这几乎不可能阅读,但我不能为我的生活弄清楚如何将任何表格布局中的任何东西粘贴/导入到这个网站......
重要的是,据我所知,这两个EXPLAIN显示了功能相同的查询计划!然而,其中一个很多比另一个快。计划者如何订购这些陈述或许有什么意义吗?我对SQL很有能力,但这个查询规划器/索引的东西正在深入研究黑暗艺术对我来说有点太过分了。任何人都可以帮忙吗?
我尝试过添加和删除索引。我尝试使用FORCE INDEX重写查询,但这只会让它们变慢。我在这里结束了我的智慧。
我唯一能想到的是,如果自我联接的两个方面都足够大(即,搜索一个非常常见的名字和一个非常常见的姓氏),那么两者的组合在某处溢出一些内存缓冲区,而不是在磁盘上处理。这似乎是唯一会在<em>某些案例中产生如此急剧减速的事情。所以这里是搜索主要(即最大)表格的一些指示性相关数字。
在主数据表(在EXPLAIN中别名为prp)中,有24,771条记录,其中Property_Class对应于&#39; First_Name&#39;以及爱德华的Property_Value&#39;和567记录的Property_Class对应于&#39; Last_Name&#39;并使用&#39; Abbott的Property_Value。&#39;搜索这些参数的查询需要很长时间才能执行,并且通常会在Web服务器完成之前超时。
相反,有916条记录,其Property_Class对应于&#39; First_Name&#39;和露丝的Property_Value&#39;和15,054条记录,其Property_Class对应于&#39; Last_Name&#39;以及戴维斯的Property_Value。&#39;搜索这些参数的查询需要0.6秒才能执行。
正如您所看到的,两个查询都可能涉及相似数量的交叉匹配(~14,000,000)。然而,一个是冰川,另一个不是。
无论如何,我已经尝试在my.ini中增加任何可能的声音缓冲类型变量以查看是否有帮助,但是我很不愿意在这方面进行太多的实验,因为我真的不喜欢&#39我不知道自己在做什么。我的编码器比数据库服务器管理员更多!
所以,如果有人对我有所了解,我很高兴听到它!
感谢您的时间。
编辑:用于将Property_Type,Person和Property_Value拼接成一个连贯条目的VIEW如下:
id,select_type,table,partitions,type,possible_keys,key,key_len,ref,rows,filtered,Extra
1,SIMPLE,ptc1,NULL,ref,"PRIMARY,Property_ID_IDX,Property_Class_ID_IDX",Property_Class_ID_IDX,4,const,2,100.00,"Using index; Using temporary; Using filesort"
1,SIMPLE,pt,NULL,eq_ref,PRIMARY,PRIMARY,4,liverpool.ptc1.Property_ID,1,100.00,NULL
1,SIMPLE,rlt,NULL,eq_ref,PRIMARY,PRIMARY,4,liverpool.pt.Record_Link_Type_ID,1,100.00,"Using where; Using index"
1,SIMPLE,prp,NULL,ref,"PRIMARY,Property_Value_IDX,Person_Record_ID_IDX",Property_Value_IDX,23,"const,liverpool.ptc1.Property_ID",13,100.00,"Using where"
1,SIMPLE,pr,NULL,eq_ref,"PRIMARY,Master_Person_ID_IDX,Person_Record_ID_IDX",PRIMARY,4,liverpool.prp.Person_Record_ID,1,100.00,"Using where"
1,SIMPLE,rt,NULL,eq_ref,"PRIMARY,Record_Type_ID",PRIMARY,4,liverpool.pr.Record_Type_ID,1,100.00,"Using index"
1,SIMPLE,pr,NULL,ref,Master_Person_ID_IDX,Master_Person_ID_IDX,17,liverpool.pr.Master_Person_ID,1,100.00,NULL
1,SIMPLE,pr,NULL,ref,"PRIMARY,Master_Person_ID_IDX,Person_Record_ID_IDX",Master_Person_ID_IDX,17,liverpool.pr.Master_Person_ID,1,100.00,Distinct
1,SIMPLE,rt,NULL,eq_ref,"PRIMARY,Record_Type_ID",PRIMARY,4,liverpool.pr.Record_Type_ID,1,100.00,"Using index; Distinct"
1,SIMPLE,ptc2,NULL,ref,"PRIMARY,Property_ID_IDX,Property_Class_ID_IDX",Property_Class_ID_IDX,4,const,5,100.00,"Using index; Distinct"
1,SIMPLE,pt,NULL,eq_ref,PRIMARY,PRIMARY,4,liverpool.ptc2.Property_ID,1,100.00,Distinct
1,SIMPLE,rlt,NULL,eq_ref,PRIMARY,PRIMARY,4,liverpool.pt.Record_Link_Type_ID,1,100.00,"Using where; Using index; Distinct"
1,SIMPLE,prp,NULL,eq_ref,"PRIMARY,Property_Value_IDX,Person_Record_ID_IDX",PRIMARY,8,"liverpool.ptc2.Property_ID,liverpool.pr.Person_Record_ID",1,5.00,"Using where; Distinct"
答案 0 :(得分:0)
这是“过度规范化”。
这是“EAV”。
将这两者放在一起,就会得到很多无法优化的JOINs
。处理必须反复进行。
(不,我不知道为什么一个查询明显慢于另一个。)
如需更多帮助,请提供SHOW CREATE TABLE
和SHOW CREATE VIEW
。