如何从两个表中加速搜索SQL查询?

时间:2017-03-07 16:07:23

标签: mysql sql

以下是一个示例,所以我有表user和表city,他们是这样的:

user列是(user_id,city_id,时间戳) [user_id和city_id是唯一的]

city列是(city_name,city_id) [city_id是唯一的]

我希望在某个城市的某个特定日期获得用户数,所以基本上我是这样做的:

select city_id, city_name, 
    (select count(user.user_id) 
     from user, city 
     where DATE_FORMAT(user.timestamp, '%Y-%m-%d') = '2017-03-07' 
     and user.city_id = ct.city_id) as user_count
from city ct 
where (city_id = 20 or city_id = 30)

结果:

city_id, city_name, user_count
20       New York   100
30       LA         200

然后我意识到这比直接搜索

要慢
select count(user.user_id) 
from user, city 
where DATE_FORMAT(user.timestamp, '%Y-%m-%d') = '2017-03-07' 
    and user.city_id = 20

这是为什么?原始搜索中的ct.city_id是否已被设置为20或30?我应该如何优化搜索并以我想要的表格格式获得结果?

3 个答案:

答案 0 :(得分:6)

您可以改进查询,避免使用内部联接和分组

进行子选择
select city_id, city_name,    count(user.user_id) 
from user
inner join city on user.city_id = city.city_id
where DATE_FORMAT(user.timestamp, '%Y-%m-%d') = '2017-03-07' 
and city_id in (city_id = 20 or city_id = 30)
group by city_id, city_name

答案 1 :(得分:0)

我会假设MySQL选择在第一个查询中将派生表实现为内部临时表,并且不会对第二个查询做出选择。

  

对于派生表(FROM子句中的子查询),优化器有以下选择:

     
      
  • 将派生表合并到外部查询块
  •   
  • 将派生表具体化为内部临时表
  •   

来源:Mysql Documentation - 8.2.2 Optimizing Subqueries, Derived Tables, and Views

答案 2 :(得分:0)

试试这个:

    private CancellationTokenSource cts;

    public async void MyButtonhandler(object sender, EventArgs e) {
        cts = new CancellationTokenSource();
        try {
            var result = await Task.Run(() => ReadAll(cts));
            if (result) {
                //success
            } else {
                //failure
            }
        } catch (TaskCanceledException ex) {

        }            
    }

    internal async Task<bool> ReadAll(CancellationTokenSource cts) {
        byte[] data = new byte[1];
        var timeout = TimeSpan.FromSeconds(10);

        var ReadAllTask = Task.Run(() => {
            // Read all information
            // [omit communication exchange via COM port]

        }, cts.Token);

        if (await Task.WhenAny(ReadAllTask, Task.Delay(timeout)) == ReadAllTask) {
            return true;
        }
        cts.Cancel();
        return false;
    }