背景:
程序列表页展示信息,需后台多表关联读取视图,视图内sql已优化(索引、语句),外层增加查询条件后速度基本一致。
VIEW:
CREATE VIEW a
AS
SELECT *
FROM b FORCE INDEX (`idx_b`)
JOIN a ON a.CId = b.Id
JOIN c ON c.CId = b.Id
LEFT JOIN s ON s.No = c.No
LEFT JOIN d ON d.CId = a.Id AND d.EId = c.Id
LEFT JOIN e FORCE INDEX (`idx_e`) ON e.CId = a.Id
WHERE b.isdeleted = 0
环境:
1).mysql 5.7.10 InnoDB引擎 2核4G
2).阿里云RDS 4核8G (貌似效果更差<分片性能会衰减>)
问题:
1.外层增加排序order by条件后,速度变慢,查看执行计划为将试图内数据转化为temp_table后再进行sort;
2.直接count视图的话更加缓慢,已达不能接受地步,列表分页肯定需展示总条数,抛除视图,直接使用sql也是很缓慢。
大神们指点指点怎样优化mysql多表关联的count
巴扎黑2017-04-17 16:22:04
根據你寫的sql語句,有幾點建議:
1、b表使用了force index以強制使用索引,在表條目數較多的情況下,索引查詢未必是最優的方式,一般情況下讓資料庫自己選擇就可以了。或是自己驗證下,用isdeleted = 0的條件查b單表,確認加上force index性能更好,否則就去掉force index。
2、統計數量的sql語句,僅保留a,b,c張表就可以了,其他的幾張表是left join,不影響統計結果
3、根據上一步取出的b表字段的主鍵字段,在php中循環取詳情資訊。因分頁的數量一般較少,多次透過主鍵取資料的方式速度可能會更快。
另外,如果想讓大家分析,最好把sql的執行計畫貼出來。
PHP中文网2017-04-17 16:22:04
多次查詢,然後合計,得出記錄總數。怎麼樣? ? (沒測試過....)
例如,每次查詢的資料量為: 8000筆記錄
PHP 代码
:
// 单位查询数据量
$unit_num = 8000;
// 查询批次
$count = 1;
// 总数据量
$total_record = 0;
while (true)
{
$sql = 'select count(*) from tb_name limit ' . ($count - 1) * $unit_num . ' , ' . $unit_num;
$part_num = $db->getOne($sql); # 部分数量
// 如果数量 和 查询的单位量相等,这说明,总数据可能更多..,继续查询
if ($part_num === $unit_num) {
$total_record += $part_num;
}
// 如果数量 比 查询的单位量更少,说明,已经是最后一批数据了
// 跳出循环
if ($part_num < $unit_num) {
$total_record += $part_num;
break;
}
# 更新查询的批次
$count++;
}
echo '总数据量:' . $total_record;
黄舟2017-04-17 16:22:04
最開始是研發將總條數做成異步加載,數據和頁碼先出來,這樣只要不是刻意查數量沒什麼太大影響;
後來看樓上建議改了下視圖,加載總數也會更快些;
還有那幾個強制索引也是為使用視圖時外面加條件能夠走索引才加的;
這樣優化下來暫時還能接受。