您好,我的应用程序中有 Angular JS 分页,我将数据发送到我的大查询,其中包括用户设置的过滤器
更新 SQL_CALC_FOUND_ROWS 这是我的问题。如何计算特定过滤器的行数。 100,000 行花了我 2 秒我需要分页数作为总数
更新: 我在这里错过了以下内部查询:
(从学生中选择 count(*) 作为inner_st,其中 st.name = inner_st.name)作为姓名,
当我删除上面的内部查询时速度要快得多
行数:50,000 用户表:4行 类(class)表:4行 索引:仅 id 作为主键
查询时间20-40秒
tables: students.
columns : id, date ,class, name,image,status,user_id,active
table user
coloumn: id,full_name,is_admin
查询
SELECT SQL_CALC_FOUND_ROWS st.id,
st.date,
st.image,
st.user_id,
st.status,
st,
ck.name AS class_name,
users.full_name,
(select count(*) from students AS inner_st where st.name = inner_st.name) AS names,
FROM students AS st
LEFT JOIN users ON st.user_id = users.user_id
LEFT JOIN classes AS ck ON st.class = ck.id
WHERE date BETWEEN '2018-01-17' AND DATE_ADD('2018-01-17', INTERVAL 1 DAY)
AND DATE_FORMAT(date,'%H:%i') >= '00:00'
AND DATE_FORMAT(date,'%H:%i') <= '23:59'
AND st.active=1
-- here I can concat filters from web like "and class= 1"
ORDER BY st.date DESC
LIMIT 0, 10
怎样才能让它更快?当我删除 order by 和 SQL_CALC_FOUND_ROWS 时速度更快,但我需要它们 我听说过索引,但只有主键是索引
最佳答案
在推荐对此查询的不同方法之前,有一些评论:
- 您是否考虑删除
SQL_CALC_FOUND_ROWS
而是运行两个查询(一个用于计数,一个用于选择数据)?在某些情况下,这可能比将它们连接到一个查询更快。 - 这些条件的目标是什么?你想达到什么目的?我们可以删除它们吗(因为它们似乎总是返回 true?)-
AND DATE_FORMAT(st.date, '%H:%i') >= '00:00' AND DATE_FORMAT(st.date, '%H:%i') <= '23:59'
- 您只需要 10 个结果,但数据库必须为 LIMIT 之前的每个结果运行“names”子查询(这可能很多?)。因此,我建议将 SELECT 子句中的子查询提取到临时表,为其建立索引并连接到它(请参阅下面的固定查询)。
为了优化查询,我们首先添加这些索引:
ALTER TABLE `classes` ADD INDEX `classes_index_1` (`id`, `name`);
ALTER TABLE `students` ADD INDEX `students_index_1` (`active`, `user_id`, `class`, `name`, `date`);
ALTER TABLE `users` ADD INDEX `users_index_1` (`user_id`, `full_name`);
现在创建临时表(最初这是 SELECT 子句中的子查询)并为其建立索引:
-- Transformed subquery to a temp table to improve performance
CREATE TEMPORARY TABLE IF NOT EXISTS temp1 AS SELECT
count(*) AS names,
name
FROM
students AS inner_st
WHERE
1 = 1
GROUP BY
name
ORDER BY
NULL
-- This index is required for optimal temp tables performance
ALTER TABLE
`temp1`
ADD
INDEX `temp1_index_1` (`name`, `names`);
修改后的查询:
SELECT
SQL_CALC_FOUND_ROWS st.id,
st.date,
st.image,
st.user_id,
st.status,
ck.name AS class_name,
users.full_name,
temp1.names
FROM
students AS st
LEFT JOIN
users
ON st.user_id = users.user_id
LEFT JOIN
classes AS ck
ON st.class = ck.id
LEFT JOIN
temp1
ON st.name = temp1.name
WHERE
st.date BETWEEN '2018-01-17' AND DATE_ADD('2018-01-17', INTERVAL 1 DAY)
AND st.active = 1
ORDER BY
st.date DESC LIMIT 0,
10
关于php - 分页查询mysql+php耗时20-40秒,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48290586/