Mysql 优化SQL查询以减少执行时间
我的SQL查询和应用的所有过滤器都返回了10万(一百万)条记录。获取所有记录需要76.28秒。。这是不可接受的。我如何优化我的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
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