why my sql query slow?

时间:2017-06-15 10:37:21

标签: mysql sql

I try to create a view which join from 4 tables (tb_user is 200 row, tb_transaction is 250.000 row, tb_transaction_detail is 250.000 row, tb_ms_location is 50 row), when i render with datatables serverside, it's take 13 secons. even when I filtering it.

I don't know why it's take too long...

here my sql query

    CREATE VIEW `vw_cashback` AS

    SELECT 
        `tb_user`.`nik` AS `nik`,
        `tb_user`.`full_name` AS `nama`,
        `tb_ms_location`.`location_name` AS `lokasi`,
        `tb_transaction`.`date_transaction` AS `tanggal_setor`,
        sum(CASE WHEN `tb_transaction_detail`.`vehicle_type`=1 THEN 1 ELSE 0 END) AS `mobil`,
        sum(CASE WHEN `tb_transaction_detail`.`vehicle_type`=2 THEN 1 ELSE 0 END) AS `motor`,
        sum(CASE WHEN `tb_transaction_detail`.`vehicle_type`=3 THEN 1 ELSE 0 END) AS `truck`,
        sum(CASE WHEN `tb_transaction_detail`.`vehicle_type`=4 THEN 1 ELSE 0 END) AS `speda`,
        sum(`tb_transaction_detail`.`total`) AS `total_global`,
        (sum(`tb_transaction_detail`.`total`) * 0.8) AS `total_user`,
        (sum(`tb_transaction_detail`.`total`) * 0.2) AS `total_tgr`,
        ((sum(`tb_transaction_detail`.`total`) * 0.2) / 2) AS `total_cashback`,
        (curdate() - cast(`tb_user`.`created_at` AS date)) AS `status`


    FROM `tb_user`
        JOIN `tb_transaction` ON `tb_user`.`id` = `tb_transaction`.`user_id`
        JOIN `tb_transaction_detail` ON `tb_transaction`.`id` = `tb_transaction_detail`.`transaction_id`
        JOIN `tb_ms_location` ON `tb_ms_location`.`id` = `tb_transaction`.`location_id`

    GROUP BY 
        `tb_user`.`id`,
        `tb_transaction`.`date_transaction`,
        `tb_user`.`nik`,
        `tb_user`.`full_name`,
        `tb_user`.`created_at`,
        `tb_ms_location`.`location_name`

thanks

1 个答案:

答案 0 :(得分:1)

未过滤的查询必须很慢,因为它会获取所有表中的所有记录,连接并聚合它们。

但是你说过滤时视图仍然很慢。问题是:你如何过滤?当您按用户,位置和交易日期汇总时,它应该是其中之一。但是,您的结果列表中没有用户标识或事务标识。这感觉不自然,我建议你添加它们,所以像

这样的查询
select * from vw_cashback where user_id = 5

select * from vw_cashback where transaction_id = 12345

是可能的。

按原样,您必须按位置名称或用户nik /名称进行过滤。因此,如果您需要它,那么为查找创建索引:

CREATE idx_location_name ON tb_ms_location(location_name, id)
CREATE idx_user_name ON tb_user(full_name, id)
CREATE idx_user_nik ON tb_user(nik, id)

后两者甚至可以转化为覆盖索引(即包含查询中使用的所有列的索引),这仍然可以加快进程:

CREATE idx_user_name ON tb_user(nik, id, full_name, created_at);
CREATE idx_user_nik ON tb_user(full_name, id, nik, created_at);

对于通过索引的访问,您还可能需要覆盖索引:

CREATE idx_location_id ON tb_ms_location(id, location_name)
CREATE idx_user_id ON tb_user(id, nik, full_name, created_at);