tencent cloud

TDSQL Boundless

单表查询

PDF
聚焦模式
字号
最后更新时间: 2026-03-26 14:54:23
本文档介绍如何在 TDSQL Boundless 数据库中对单表数据进行高效查询,包括基础查询语法、查询优化技巧以及 TDSQL Boundless 特有的优化机制。

开始之前

在进行单表查询之前,请确保:
1. 已创建 TDSQL Boundless 实例
2. 已导入测试数据:本文档使用 TPC-H 基准测试数据集作为示例,详情请参考 TPC-H 基准测试数据模型参考
3. 已建立数据库连接:通过 MySQL 客户端或应用程序连接到 TDSQL Boundless。

简单查询

最基础的查询操作是从表中读取特定列的数据。

基本 SELECT 语句

查询客户的基本信息:
SELECT c_custkey, c_name, c_mktsegment FROM customer;
查询订单的关键字段:
SELECT o_orderkey, o_custkey, o_orderdate, o_totalprice FROM orders;

查询所有列

使用 * 可以查询表中的所有列:
SELECT * FROM customer;
实践教程
在生产环境中,避免使用 SELECT *,应显式指定需要的列。
原因:减少网络传输量、提高查询性能、避免读取不必要的大字段(如 c_comment)。

使用别名

为列或表指定别名可以提高 SQL 的可读性:
SELECT
c_custkey AS customer_id,
c_name AS customer_name,
c_acctbal AS account_balance
FROM customer AS c;

对结果进行筛选

使用 WHERE 子句可以过滤查询结果,只返回满足条件的数据。

等值条件查询

查询特定市场细分的客户:
SELECT c_custkey, c_name, c_acctbal
FROM customer
WHERE c_mktsegment = 'AUTOMOBILE';
查询特定订单状态的订单:
SELECT o_orderkey, o_orderdate, o_totalprice
FROM orders
WHERE o_orderstatus = 'O'; -- O: Open, F: Finished, P: Pending

比较条件查询

查询账户余额大于5000的客户:
SELECT c_custkey, c_name, c_acctbal
FROM customer
WHERE c_acctbal > 5000.00;
查询1995年之后的订单:
SELECT o_orderkey, o_orderdate, o_totalprice
FROM orders
WHERE o_orderdate >= '1995-01-01';

范围查询

使用 BETWEEN 进行范围查询:
SELECT o_orderkey, o_orderdate, o_totalprice
FROM orders
WHERE o_orderdate BETWEEN '1995-01-01' AND '1995-12-31';

多条件组合

使用 ANDOR 组合多个条件:
SELECT c_custkey, c_name, c_acctbal, c_mktsegment
FROM customer
WHERE c_mktsegment = 'AUTOMOBILE'
AND c_acctbal > 5000.00;

模糊查询

使用 LIKE 进行模糊匹配:
SELECT c_custkey, c_name
FROM customer
WHERE c_name LIKE 'Customer%';

对结果进行排序

使用 ORDER BY 子句可以对查询结果进行排序。

升序排序(默认)

按订单日期升序排列:
SELECT o_orderkey, o_orderdate, o_totalprice
FROM orders
ORDER BY o_orderdate;
或显式指定 ASC
SELECT o_orderkey, o_orderdate, o_totalprice
FROM orders
ORDER BY o_orderdate ASC;

降序排序

查询账户余额最高的客户:
SELECT c_custkey, c_name, c_acctbal
FROM customer
ORDER BY c_acctbal DESC;
查询最近的订单:
SELECT o_orderkey, o_orderdate, o_totalprice
FROM orders
ORDER BY o_orderdate DESC;

多列排序

可以按多个列进行排序,优先级从左到右:
SELECT o_orderkey, o_orderdate, o_totalprice, o_orderpriority
FROM orders
ORDER BY o_orderdate DESC, o_totalprice DESC;

排序优化建议

TDSQL Boundless 优化要点
1. 索引优化:在 ORDER BY 的列上建立索引,避免 filesort
2. 覆盖索引:如果查询的列都在索引中,TDSQL Boundless 可以直接从索引读取,无需回表。
3. 索引顺序ORDER BY 的列顺序应与索引定义顺序一致。
示例:优化排序性能
-- 创建组合索引
CREATE INDEX idx_orderdate_totalprice ON orders(o_orderdate DESC, o_totalprice DESC);

-- 此查询可以直接使用索引,避免排序
SELECT o_orderkey, o_orderdate, o_totalprice
FROM orders
ORDER BY o_orderdate DESC, o_totalprice DESC;
通过 EXPLAIN 查看执行计划:
EXPLAIN SELECT o_orderkey, o_orderdate, o_totalprice
FROM orders
ORDER BY o_orderdate DESC;
如果执行计划中没有 Using filesort,说明使用了索引排序,性能最优。

限制查询结果数量

使用 LIMIT 子句可以限制返回的结果行数,常用于分页查询或获取 Top N 结果。

获取前 N 条记录

查询前10个最大金额的订单:
SELECT o_orderkey, o_orderdate, o_totalprice
FROM orders
ORDER BY o_totalprice DESC
LIMIT 10;
查询账户余额最高的前20名客户:
SELECT c_custkey, c_name, c_acctbal
FROM customer
ORDER BY c_acctbal DESC
LIMIT 20;

分页查询

使用 LIMIT offset, countLIMIT count OFFSET offset 进行分页:
方式一:
-- 查询第 2 页数据(每页 20 条)
SELECT c_custkey, c_name, c_acctbal
FROM customer
ORDER BY c_custkey
LIMIT 20, 20; -- offset=20, count=20
方式二(推荐):
-- 更清晰的写法
SELECT c_custkey, c_name, c_acctbal
FROM customer
ORDER BY c_custkey
LIMIT 20 OFFSET 20;

LIMIT 优化机制

TDSQL Boundless 的 LIMIT 优化
1. 提前终止扫描
TDSQL Boundless 在扫描到足够的数据后会立即停止,不会扫描整个表。
例如 LIMIT 10 只需找到10条数据即可返回。
2. 索引下推
如果查询条件和排序字段都有索引,TDSQL Boundless 会在存储引擎层就应用 LIMIT
减少数据传输和内存使用。
3. TopN 优化
ORDER BY ... LIMIT N 会使用堆排序算法,空间复杂度 O(N)。
避免全表排序,性能提升显著。
性能对比示例:
-- 无 LIMIT:需要扫描全表并排序
SELECT o_orderkey, o_totalprice
FROM orders
ORDER BY o_totalprice DESC;
-- 扫描行数: 1,500,000 (全表)

-- 有 LIMIT:提前终止
SELECT o_orderkey, o_totalprice
FROM orders
ORDER BY o_totalprice DESC
LIMIT 10;
-- 扫描行数: ~10(使用索引)或使用堆排序优化

分页优化建议

深度分页问题
-- 性能差:需要扫描并跳过前 1,000,000 行
SELECT o_orderkey, o_orderdate
FROM orders
ORDER BY o_orderkey
LIMIT 1000000, 20;
优化方案:使用范围查询代替 OFFSET
-- 方式一:记录上次查询的最大 ID
SELECT o_orderkey, o_orderdate
FROM orders
WHERE o_orderkey > 1000000 -- 上次最后一条记录的 ID
ORDER BY o_orderkey
LIMIT 20;

-- 方式二:使用覆盖索引 + 延迟关联
SELECT o.o_orderkey, o.o_orderdate, o.o_totalprice
FROM orders o
INNER JOIN (
SELECT o_orderkey
FROM orders
ORDER BY o_orderkey
LIMIT 1000000, 20
) tmp ON o.o_orderkey = tmp.o_orderkey;

聚合查询

聚合查询用于对数据进行统计分析,常用的聚合函数包括 COUNTSUMAVGMAXMIN 等。

基础聚合函数

统计总订单数:
SELECT COUNT(*) AS total_orders
FROM orders;
统计总销售额:
SELECT SUM(o_totalprice) AS total_sales
FROM orders;
查询最大和最小订单金额:
SELECT
MAX(o_totalprice) AS max_order_amount,
MIN(o_totalprice) AS min_order_amount,
AVG(o_totalprice) AS avg_order_amount
FROM orders;

分组聚合

使用 GROUP BY 对数据进行分组统计。
统计每个市场细分的客户数量:
SELECT
c_mktsegment,
COUNT(*) AS customer_count
FROM customer
GROUP BY c_mktsegment
ORDER BY customer_count DESC;
统计每年的订单数量和总销售额:
SELECT
YEAR(o_orderdate) AS order_year,
COUNT(*) AS order_count,
SUM(o_totalprice) AS total_sales,
AVG(o_totalprice) AS avg_order_amount
FROM orders
GROUP BY YEAR(o_orderdate)
ORDER BY order_year DESC;
统计每个订单状态的订单数量:
SELECT
o_orderstatus,
COUNT(*) AS status_count,
SUM(o_totalprice) AS total_amount
FROM orders
GROUP BY o_orderstatus;

HAVING 子句

HAVING 用于过滤分组后的结果(与 WHERE 过滤原始行不同)。
查询订单数量超过1000的客户:
SELECT
o_custkey,
COUNT(*) AS order_count,
SUM(o_totalprice) AS total_spent
FROM orders
GROUP BY o_custkey
HAVING COUNT(*) > 1000
ORDER BY total_spent DESC;
查询平均订单金额大于10000的年份:
SELECT
YEAR(o_orderdate) AS order_year,
AVG(o_totalprice) AS avg_amount
FROM orders
GROUP BY YEAR(o_orderdate)
HAVING AVG(o_totalprice) > 10000
ORDER BY order_year;

去重统计

使用 DISTINCT 进行去重统计:
统计不同市场细分的数量:
SELECT COUNT(DISTINCT c_mktsegment) AS segment_count
FROM customer;
统计有订单的客户数量:
SELECT COUNT(DISTINCT o_custkey) AS active_customers
FROM orders;

聚合查询优化

TDSQL Boundless 聚合查询优化要点
1. 索引加速分组
-- 在 GROUP BY 列上建立索引
CREATE INDEX idx_mktsegment ON customer(c_mktsegment);

-- 此查询可以利用索引加速分组
SELECT c_mktsegment, COUNT(*)
FROM customer
GROUP BY c_mktsegment;
2. 松散索引扫描(Loose Index Scan)
GROUP BY 的列是索引前缀时,TDSQL Boundless 可以跳过不相关的索引记录。
通过 EXPLAIN 查看是否使用了 Using index for group-by
3. 覆盖索引优化
-- 创建覆盖索引
CREATE INDEX idx_orderdate_totalprice ON orders(o_orderdate, o_totalprice);

-- 此查询无需回表,直接从索引读取
SELECT
YEAR(o_orderdate) AS order_year,
SUM(o_totalprice) AS total_sales
FROM orders
GROUP BY YEAR(o_orderdate);
4. 分区表加速
如果表按日期分区,聚合查询可以并行在各分区上执行。
TDSQL Boundless 会自动进行分区裁剪,只扫描相关分区。
-- 假设 orders 表按年份分区
-- 此查询只扫描 1995 年的分区
SELECT
COUNT(*) AS order_count,
SUM(o_totalprice) AS total_sales
FROM orders
WHERE o_orderdate BETWEEN '1995-01-01' AND '1995-12-31';

帮助和支持

本页内容是否解决了您的问题?

填写满意度调查问卷,共创更好文档体验。

文档反馈