Php 如何在不改变数据库结构的情况下提高Mysql数据库性能

Php 如何在不改变数据库结构的情况下提高Mysql数据库性能,php,mysql,mysqli,phpmyadmin,mysql-workbench,Php,Mysql,Mysqli,Phpmyadmin,Mysql Workbench,我有一个已经在使用的数据库,我必须提高使用该数据库的系统的性能 在一个循环中有两个主要查询运行大约1000次,并且每个查询都与其他3个表进行内部连接。这反过来又使系统变得非常缓慢。 实际上,我试图从循环中删除查询,只提取一次所有数据,然后在PHP中进行处理。但是这会给内存RAM带来很大的负载,如果有两个或更多的客户端尝试使用该系统,系统就会挂起 即使删除了过期数据,表中仍有大量数据。 我已附上以下问题。 有人能帮我解决这个问题吗 从库存中选择* 其中,region_id=38或region_id

我有一个已经在使用的数据库,我必须提高使用该数据库的系统的性能

在一个循环中有两个主要查询运行大约1000次,并且每个查询都与其他3个表进行内部连接。这反过来又使系统变得非常缓慢。 实际上,我试图从循环中删除查询,只提取一次所有数据,然后在PHP中进行处理。但是这会给内存RAM带来很大的负载,如果有两个或更多的客户端尝试使用该系统,系统就会挂起

即使删除了过期数据,表中仍有大量数据。 我已附上以下问题。 有人能帮我解决这个问题吗

从库存中选择* 其中,region_id=38或region_id=-1 和tour_opp_id=410或tour_opp_id=-1 房间平面图id=141,膳食平面图id=1,床类型id=1,酒店id=1059 并在供应商代码中找到“QOA、QTE、QM、TEST、TEST1、MQE1、MQE3、PERR、QKT” 以及“2014-11-14”,自即日起至即日止 按酒店id描述、供应商代码描述、地区id描述、旅游opp id描述、库存、库存id描述订购 选择*,pinfo.fri作为pi_day_fri,pinfoadd.fri作为pa_day_fri,pinfochld.fri作为pc_day_fri 从“利润”到“加价”` pinfo.profit\u id=profit\u markup.profit\u markup\u id上的pinfo作为内部联接profit\u markup\u信息 内部连接利润\标记\添加\信息作为pinfoadd上的pinfoadd.profit\ id=利润\标记.利润\标记\ id pinfochld.profit\u id=profit\u markup.profit\u markup\u id上作为pinfochld的内部联接profit\u markup\u child\u信息 其中profit\u markup.hotel\u id=1059,'booking\u channel`=1或'booking\u channel`=2 和'rate\u region`=-1或'rate\u region`=128 期间_from='2014-11-14' 按利润加成的订单。酒店标识说明、供应商代码说明、费率地区说明、运营商列表说明、利润加成标识说明
对于第一个查询,我不确定您是否可以做很多工作,假设您已经为您排序的字段编制了索引,除了用列名替换*之外,不要指望这会大幅提高性能

对于第二个查询,在执行循环并输入选择参数之前,可以创建一个视图,其中所有表都已连接并排序,然后生成一条准备好的语句,从视图中进行选择,并在循环中绑定参数

另外,如果您的php服务器和数据库服务器位于两个不同的位置,那么最好通过数据库中的存储过程进行选择


如果什么都不起作用,那么memcache就是最好的选择。。。虽然我个人从未这样做过,但您提高了查询性能,而不是数据库性能

对于这两个查询,WHERE和ONJoin子句列上都有第一个check索引,如果缺少索引,则必须添加索引以提高查询性能

在创建索引之前选中“解释平面”


如果可能的话,请告诉我这两个问题的解释平面,这将对我们有所帮助

因为我们没有看到您的节目创建表格;并解释扩展计划。很难给你一个答案

但总的来说,关于你的问题,顺便说一句,我在下面重新写过

SELECT 
    hotel_id, supplier_code, region_id, tour_opp_id, inventory_id
FROM 
    inventory
WHERE 
    region_id IN (38, -1) 
    AND tour_opp_id IN (410, -1) 
    AND room_plan_id IN (141, 1) 
    AND bed_type_id IN (1, 1059)
    AND supplier_code IN ('QOA', 'QTE', 'QM', 'TEST', 'TEST1', 'MQE1', 'MQE3', 'PERR', 'QKT')  
    AND ('2014-11-14' BETWEEN from_date AND to_date )
ORDER BY 
    hotel_id DESC, supplier_code DESC, region_id DESC, tour_opp_id DESC, inventory_id DESC
SELECT 
    *, pinfo.fri as pi_day_fri,
    pinfoadd.fri as pa_day_fri, 
    pinfochld.fri as pc_day_fri
FROM
    profit_markup
INNER JOIN 
    profit_markup_info AS pinfo ON pinfo.profit_id = profit_markup.profit_markup_id
INNER JOIN 
    profit_markup_add_info AS pinfoadd ON pinfoadd.profit_id = profit_markup.profit_markup_id
INNER JOIN 
    profit_markup_child_info AS pinfochld ON pinfochld.profit_id = profit_markup.profit_markup_id
WHERE  
    profit_markup.hotel_id = 1059 
    AND booking_channel IN (1, 2) 
    AND rate_region IN (-1, 128) 
    AND period_from <= '2014-11-14' 
    AND period_to >= '2014-11-14'
ORDER BY 
    profit_markup.hotel_id DESC, supplier_code DESC, rate_region DESC,
    operators_list DESC, profit_markup_id DESC
不要使用*获取所有列。你应该列出你真正需要的栏目。使用*只是编写查询的一种懒惰方式。限制列将限制所选的数据大小

更新/插入/删除库存中的记录的频率是多少?如果不是太频繁,那么可以考虑使用Sql缓存。但是,如果使用查询并且经常更新库存表,则缓存查询将导致问题。此外,要使用查询缓存,必须在服务器上检查query\u cache\u type的值。显示全局变量,如“查询\缓存\类型”;。如果该值设置为0,则缓存功能将被禁用,SQL\U缓存将被忽略。如果将其设置为1,则服务器将缓存所有查询,除非您告诉它不要使用NO_SQL_缓存。如果该选项设置为2,那么MySQL将仅在使用SQL\U cache子句的地方缓存查询

如果您在此订单中的以下列上有索引,它将帮助您获得酒店id、供应商代码、地区id、旅游opp id、库存id

如果可能的话,增加服务器上的排序缓冲区大小,因为这里最可能出现的问题是您的排序太多

至于第二个问题,顺便说一句,我在下面重新写了一遍

SELECT 
    hotel_id, supplier_code, region_id, tour_opp_id, inventory_id
FROM 
    inventory
WHERE 
    region_id IN (38, -1) 
    AND tour_opp_id IN (410, -1) 
    AND room_plan_id IN (141, 1) 
    AND bed_type_id IN (1, 1059)
    AND supplier_code IN ('QOA', 'QTE', 'QM', 'TEST', 'TEST1', 'MQE1', 'MQE3', 'PERR', 'QKT')  
    AND ('2014-11-14' BETWEEN from_date AND to_date )
ORDER BY 
    hotel_id DESC, supplier_code DESC, region_id DESC, tour_opp_id DESC, inventory_id DESC
SELECT 
    *, pinfo.fri as pi_day_fri,
    pinfoadd.fri as pa_day_fri, 
    pinfochld.fri as pc_day_fri
FROM
    profit_markup
INNER JOIN 
    profit_markup_info AS pinfo ON pinfo.profit_id = profit_markup.profit_markup_id
INNER JOIN 
    profit_markup_add_info AS pinfoadd ON pinfoadd.profit_id = profit_markup.profit_markup_id
INNER JOIN 
    profit_markup_child_info AS pinfochld ON pinfochld.profit_id = profit_markup.profit_markup_id
WHERE  
    profit_markup.hotel_id = 1059 
    AND booking_channel IN (1, 2) 
    AND rate_region IN (-1, 128) 
    AND period_from <= '2014-11-14' 
    AND period_to >= '2014-11-14'
ORDER BY 
    profit_markup.hotel_id DESC, supplier_code DESC, rate_region DESC,
    operators_list DESC, profit_markup_id DESC
再次从查询中删除*的使用

确保以下列具有相同的类型/排序规则和相同的大小。pinfo.profit\u id、profit\u markup.profit\u id、pinfoadd.profit\u id、pinfochld.profit\u id,每个表上都必须有一个索引。如果列具有不同的类型,那么MySQL每次都必须转换数据以加入记录。即使你有索引,它也会变慢。此外,如果这些列是字符类型,即VARCHAR,请确保它们是具有拉丁1_general_ci排序规则的字符,这将 更快地查找ID,但如果您使用INT,则会更好

使用我为上一个查询列出的第3个和第4个技巧

试着使用直链,你必须知道你在这里做什么,否则它会咬你!这里有一个关于这个的好线索


我希望这有帮助。

您能演示一下如何创建表吗?另外,你能展示一下你对队列的解释吗?还有,服务器规格是什么?为什么使用*而不是列出字段?另外,你能展示一下你是如何循环记录的吗。这些表格是如何每分钟/秒/小时更新的???您在中使用或代替的任何原因?