Mysql 优化SQL查询以减少执行时间

Mysql 优化SQL查询以减少执行时间,mysql,Mysql,我的SQL查询和应用的所有过滤器都返回了10万(一百万)条记录。获取所有记录需要76.28秒。。这是不可接受的。我如何优化我的SQL查询,这应该花费更少的时间。 我使用的查询是: SELECT cDistName , cTlkName, cGpName, cVlgName , cMmbName , dSrvyOn FROM sspk.villages LEFT JOIN gps ON nVlgGpID = nGpID LEFT JOIN TA

我的SQL查询和应用的所有过滤器都返回了10万(一百万)条记录。获取所有记录需要76.28秒。。这是不可接受的。我如何优化我的SQL查询,这应该花费更少的时间。 我使用的查询是:

    SELECT cDistName , cTlkName, cGpName, cVlgName , 
           cMmbName , dSrvyOn 
      FROM sspk.villages 
 LEFT JOIN gps  ON nVlgGpID = nGpID
 LEFT JOIN TALUKS ON nGpTlkID = nTlkID   
 left JOIN dists ON nTlkDistID = nDistID
 LEFT JOIN HHINFO ON nHLstGpID = nGpID
 LEFT JOIN MEMBERS ON nHLstID = nMmbHhiID
 LEFT JOIN BNFTSTTS  ON nMmbID = nBStsMmbID
 LEFT JOIN STATUS ON nBStsSttsID = nSttsID
 LEFT JOIN  SCHEMES ON  nBStsSchID = nSchID
     WHERE (
               (nMmbGndrID = 1 and nMmbAge between 18 and 60) 
           or  (nMmbGndrID = 2 and nMmbAge between 18 and 55)
           )
      AND cSttsDesc like 'No, Eligible' 
      AND DATE_FORMAT(dSrvyOn , '%m-%Y') < DATE_FORMAT('2012-08-01' , '%m-%Y' )
 GROUP BY cDistName , cTlkName, cGpName, cVlgName , 
        DATE_FORMAT(dSrvyOn , '%m-%Y')
选择cDistName、cTlkName、cGpName、cVlgName、,
cMmbName,dSrvyOn
来自sspk.3村庄
nVlgGpID=nGpID上的左连接gps
nGpTlkID=nTlkID上的左连接TALUKS
nTlkDistID=nDistID上的左连接区
nHLstGpID=nGpID上的左连接HHINFO
nHLstID=nMmbHhiID上的左联接成员
nMmbID=nBStsMmbID上的左连接BNFTSTTS
nBStsSttsID=nSttsID上的左连接状态
nBStsSchID=nSchID上的左连接方案
在哪里(
(nMmbGndrID=1,nMmbAge介于18和60之间)
或(nMmbGndrID=2,nMmbAge介于18和55之间)
)
和cSttsDesc,如“不,符合条件”
和日期格式(dSrvyOn,'%m-%Y')<日期格式('2012-08-01','%m-%Y'))
按cDistName、cTlkName、cGpName、cVlgName、,
日期格式(dSrvyOn,“%m-%Y”)

我在论坛内外搜索过,并使用了一些给出的提示,但几乎没有什么区别。我在上面的查询中使用的联接是主键和外键上的全部联接。有谁能建议我如何修改此sql以减少执行时间……

尝试向nMmbGndrID、nMmbAge和cSttsDesc添加索引,看看这是否有助于您的查询


此外,您还可以在select语句之前使用“Explain”命令,为您提供一些提示,说明您可以做得更好。有关解释的更多详细信息,请参阅。

此SQL有许多多余的内容,可能不会在
解释中显示

如果需要字段,它不应该位于左联接中的表中-左联接用于数据可能位于联接表中的时间,而不是必须位于联接表中的时间

如果所有必填字段都在同一个表中,那么它应该是第一个FROM中的

如果您的文本搜索是可预测的(不是来自用户输入),并且与单个已知ID相关,请使用该ID而不是文本搜索(Patricia的道具,用于发现类似的瓶颈)

由于缺少表提示,您的查询很难读取,但字段名似乎有一种模式

您需要
nMmbGndrID
nMmbAge
才能有一个值,但这些值可能位于成员中,即左下5个联接。那是多余的

请记住,您可以执行以下简单的联接:

来自sspk.villages、gps、TALUKS、dists、HHINFO、成员[…],其中[…]nVlgGpID=nGpID
和nGpTlkID=nTlkID
和nTlkDistID=nDistID
和nHLstGpID=nGpID
而nHLstID=nMmbHhiID


它看起来像
cSttsDesc
来自
STATUS
。但是,如果文本
'No,qualified'
BNFTSTTS
中的一个nBStsSttsID正好匹配,则找出该值并使用它!如果是7,则取出nBStsSttsID=nSttsID上的
左连接状态
,并用
和nBStsSttsID='7'
替换
和csttdesc,如'No,qualified'
。这将大大提高速度。

如果联接中使用的表最不适用于更新查询,那么您可能可以将引擎类型从INNODB更改为MyISAM


MyISAM中的Select查询运行速度比INNODB快2倍,但MyISAM中的更新和插入查询速度要慢得多。

您可以创建视图,以避免长时间的查询。

您声称您的连接基于良好且唯一的索引。因此,没有什么需要优化的。也许有一些提示:

  • 尝试优化表布局,也许可以减少所需的联接数。这可能会带来比其他任何东西更多的性能优化

  • 检查您的硬件(可用内存和其他东西)和服务器配置

  • 使用mysqls
    explain
    功能查找瓶颈

  • 也许您可以专门为这个查询创建一个辅助表,它由后台进程填充。这样,查询本身运行得更快,因为工作是在后台查询之前完成的。如果查询检索的数据不一定与数据库中的每一个更改都同步,则通常可以这样做

  • 检查RDBMS是否真的是正确的数据库类型。出于许多目的,图形数据库效率更高,并提供更好的性能


您的
like
操作员可能会阻碍您——使用
like
进行全文搜索并不是MySQL的强项

考虑在
cSttsDesc
上设置全文索引(首先确保它是
TEXT
字段)

或者,您可以设置布尔标志,而不是像“否,合格”这样的
cSttsDesc


来源:

先生,你是一个要求很高的MySQL用户!从大规模连接的结果集中检索到的一百万条记录的速度是每条记录76微秒。许多人认为这是可以接受的表现。请记住,您的客户机软件可能是具有如此大的结果集的一个限制因素:它必须消耗巨大的结果集并对其进行处理

尽管如此,我发现了几个问题

首先,重写查询,使每个列名都由表名限定。您将为自己和下一个维护它的人执行此操作。您可以一目了然地看到您的
标准需要在哪里执行哪些操作

第二,考虑这个搜索标准。它需要两次搜索,因为

 WHERE (
           (MEMBERS.nMmbGndrID = 1 and MEMBERS.nMmbAge between 18 and 60) 
       or  (MEMBERS.nMmbGndrID = 2 and MEMBERS.nMmbAge between 18 and 55)
       )
我猜这些标准符合你们大多数人的要求——女性18-60岁,男性18-55岁(一个猜测)。能否将MEMBERS表放在左联接列表的第一位?或者您可以在表中放入派生列(MEMBERS.working_age=1或类似的列)

WHERE ( (MEMBERS.nMmbGndrID = 1 and MEMBERS.nMmbAge between 18 and 60) or (MEMBERS.nMmbGndrID = 2 and MEMBERS.nMmbAge between 18 and 55) )
  AND DATE_FORMAT(dSrvyOn , '%m-%Y') < DATE_FORMAT('2012-08-01' , '%m-%Y' )
  AND dSrvyOn >= '2102-08-01'
  AND dSrvyOn <  '2012-08-01' + INTERVAL 1 MONTH