使用SQLite,得到一个包含~10列的表。 Theres~2500万行。
该表在'sid,uid,area,type'上有一个INDEX。
我像这样运行一个选择:
SELECT sid from actions where uid=1234 and area=1 and type=2
返回1571结果, 4分钟完成。
这样吗?
我远离SQL专家,所以希望有人可以填补我所缺少的内容。为什么这可能需要4分钟以上的所有索引?
有关实现高SQL性能的任何建议资源吗?我觉得很多谷歌的结果只是给我意见或轶事,我不介意一本坚实的书。
答案 0 :(得分:5)
改为创建uid+area+type
索引,或uid+area+type+sid
答案 1 :(得分:2)
索引不是很有用,因为它从错误的字段开始...这意味着表扫描。
看起来你有一台普通的电脑,而不是数据库。我在我的低端数据库服务器上在大约一分钟内运行超过6.5亿行的表扫描,但这意味着从光盘读取大约每秒一千兆字节,这是一个10k RM光盘的RAID - RAID 10.基本上就是说。 ..数据库爱IO,并且在某种程度上你从未见过。基本上更大的数据库服务器有许多光盘来满足IOPS(每秒IO)的要求。我见过一台装有190张碟片的服务器。
所以,你有两个选择:提高你的IOPS能力(意味着花钱),或设置因为它们“适当”而被使用的指数。
正确表示:如果索引包含的字段从左到右使用,则索引仅有用。不一定是相同的顺序......但是如果遗漏某个字段,SQL系统有可能决定不值得追求索引,而是进行表扫描(如你的情况)。
答案 2 :(得分:2)
由于索引以sid列开头,因此它必须对索引或表进行扫描(从头开始,读到结尾)以查找与其他3列匹配的数据。这意味着它必须读取所有2500万行才能找到答案。即使它只读取索引的行而不是表,这也是很多工作。
想象一下纽约大都会区的电话簿,由(以'索引'开头)姓氏组成。
您提交了SELECT [Last Name] FROM NewYorkPhoneBook WHERE [First Name] = 'Thelma'
它必须阅读所有2500万个条目才能找到所有这些Thelmas。除非您指定姓氏,然后可以直接转到姓氏首次出现的页面(搜索),或者使用First Name组织索引(索引搜索后跟表格上的搜索,也称为“书签查找”),没有办法解决它。
您要创建的用于加快查询速度的索引位于uid, area, type
。您可以包含sid,但如果sid是主键的一部分则将其保留。
注意:表通常有多个索引。请注意,索引越多,写入性能越慢。不必要的索引可能会降低整体性能,有时甚至是根本性的。测试和最终经验将有助于指导您。此外,将其作为一个现实世界的问题(如我的电话簿示例)推理可以提供帮助。如果电话簿(和单独的电话簿索引)没有意义,那么它在数据库中可能没有用。
还有一件事:即使您在这些列上放置索引,如果您的查询最终会在主表中拉出很大一部分行,那么扫描表格仍然会更便宜而不是书签查找(寻找索引然后为找到的每一行寻找表)。使用搜索进行书签查找或进行表扫描的确切“转折点”并不是我可以告诉你的,但它基于可靠的数学。
答案 3 :(得分:0)
当您在uid,area和type上创建新索引时,您还应该对每个索引执行select unique以确定哪个条目具有最少的不同条目,然后创建索引,使得它们之前显示的差异越少在索引定义中。