SQL查询速度慢?应该是吗?

SQL查询速度慢?应该是吗?,sql,performance,sqlite,indexing,Sql,Performance,Sqlite,Indexing,使用SQLite,得到了一个约10列的表。大约有2500万排 该表在“sid、uid、area、type”上有索引 我运行了一个选择,如下所示: SELECT sid from actions where uid=1234 and area=1 and type=2 这将返回1571个结果,需要4分钟才能完成 这是正常的吗 我远非SQL专家,所以希望有人能告诉我我缺少什么。为什么这可能需要4分钟以上的时间将所有内容编入索引 有什么推荐的资源可以学习如何实现高SQL性能?我觉得很多谷歌搜索结果只

使用SQLite,得到了一个约10列的表。大约有2500万排

该表在“sid、uid、area、type”上有索引

我运行了一个选择,如下所示:

SELECT sid from actions where uid=1234 and area=1 and type=2
这将返回1571个结果,需要4分钟才能完成

这是正常的吗

我远非SQL专家,所以希望有人能告诉我我缺少什么。为什么这可能需要4分钟以上的时间将所有内容编入索引


有什么推荐的资源可以学习如何实现高SQL性能?我觉得很多谷歌搜索结果只是给我一些意见或轶事,我不介意一本坚实的书。

创建
uid+area+type
索引,或者
uid+area+type+sid
  • 索引没有真正的用处,因为它确实从错误的字段开始。。。这意味着一个表格扫描

  • 看起来你有一台普通的电脑,而不是数据库。我在我的低端db服务器上大约一分钟内扫描了6.5亿行,但这意味着从磁盘上每秒读取大约1 GB的数据,这是一个由10k RM磁盘组成的RAID—RAID 10。只是说基本上。。。数据库对IO的喜爱程度是前所未有的。基本上,较大的db服务器有许多磁盘来满足IOPS(每秒IO)要求。我见过一台有190张光盘的服务器

  • 所以,你有两个选择:增强你的IOPS能力(意味着花钱),或者建立指数,因为它们是“合适的”


    正确的方法:索引仅在其包含的字段从左到右使用时才有用。不一定是同一顺序。。。但是,如果某个字段丢失,SQL系统可能会认为它不值得继续索引,而是进行表扫描(如您的情况)。

    由于索引以sid列开始,它必须扫描索引或表(从开头开始,读取到结尾),以找到与其他3列匹配的数据。这意味着它必须读取所有2500万行才能找到答案。即使它只是读取索引的行而不是表,这也是一项很大的工作

    想象一下,一本大纽约大都会区的电话簿,由姓、名(上面有“索引”)组织

    您提交
    从纽约电话簿中选择[Last Name],其中[First Name]=“Thelma”

    它必须阅读所有2500万条条目才能找到所有这些信息。除非您指定姓氏,然后可以直接转到姓氏最先出现的页面(查找),或者按姓氏组织索引(在索引上查找,然后在表上查找,也称为“书签查找”),否则无法绕过它

    为加快查询速度而创建的索引位于
    uid,area,type
    上。您可以包括sid,但如果sid是主键的一部分,则可以省略它

    注意:表通常有多个索引。请注意,索引越多,写入性能越慢。不必要的索引会降低总体性能,有时甚至会从根本上降低性能。测试和最终的经验将在这方面帮助指导您。另外,把它作为一个现实世界的问题进行推理(比如我的电话簿示例)也会很有帮助。如果它对电话簿(和单独的电话簿索引)没有意义,那么它在数据库中可能就没有意义了


    还有一件事:即使您在这些列上放置了索引,如果您的查询最终将在主表中提取很大比例的行,那么扫描该表仍然比进行书签查找便宜(查找索引,然后为找到的每一行查找表)。确切的“临界点”是通过搜索进行书签查找,还是进行表格扫描,我不能马上告诉你,但这是基于可靠的数学基础。

    当你在uid、area和type上创建新索引时,你还应该在每个索引上执行select distinct,以确定哪个条目的不同项最少,然后创建索引,使差异越小,它们就越早出现在索引定义中。

    这里有很多很好的回复,谢谢大家。所以我觉得我的眼睛睁得大大的——那么说有时候表有多个索引公平吗?似乎单个索引代表了一种常用的搜索方法。如果我有时按sid搜索,有时按uid+区域+类型搜索,那么将它们作为两个单独的索引对我来说是一个好主意吗?谢谢,有时候一个表会有很多索引-完全正常。最后一个退路是使用单字段索引,并使用服务器智能工具来有效地处理这一问题(ShiqhSQLLite可能不会),这是为什么呢?如果在where或join子句中始终同时包含uid、area和type,则没有区别。如果某个子集是常用的,那么最重要的是将该子集的列放在第一位,而不是根据选择性来安排事情。最后,如果在其他方面是相等的(假设所有三列都被用作相同的单一标准),你不想把选择性最高的列放在第一位,而不是像你建议的那样把选择性最低的列放在第一位吗?