TDSQL Boundless 单表查询

这篇档介绍如何在 TDSQL Boundless 数据库中对单表数据进行高效查询,包括基础查询语法、查询优化技巧以及 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_balanceFROM customer AS c;

六、对结果进行筛选

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

七、等值条件查询

查询特定市场细分的客户:

SELECT c_custkey, c_name, c_acctbalFROM customerWHERE c_mktsegment = 'AUTOMOBILE';

查询特定订单状态的订单:

SELECT o_orderkey, o_orderdate, o_totalpriceFROM ordersWHERE o_orderstatus = 'O'; — O: Open, F: Finished, P: Pending

八、比较条件查询

查询账户余额大于5000的客户:

SELECT c_custkey, c_name, c_acctbalFROM customerWHERE c_acctbal > 5000.00;

查询1995年之后的订单:

SELECT o_orderkey, o_orderdate, o_totalpriceFROM ordersWHERE o_orderdate >= '1995-01-01';

九、范围查询

使用 BETWEEN 进行范围查询:

SELECT o_orderkey, o_orderdate, o_totalpriceFROM ordersWHERE o_orderdate BETWEEN '1995-01-01' AND '1995-12-31';

十、多条件组合

使用 AND、OR 组合多个条件:

SELECT c_custkey, c_name, c_acctbal, c_mktsegmentFROM customerWHERE c_mktsegment = 'AUTOMOBILE' AND c_acctbal > 5000.00;

十一、模糊查询

使用 LIKE 进行模糊匹配:

SELECT c_custkey, c_nameFROM customerWHERE c_name LIKE 'Customer%';

十二、对结果进行排序

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

十三、升序排序(默认)

按订单日期升序排列:

SELECT o_orderkey, o_orderdate, o_totalpriceFROM ordersORDER BY o_orderdate;

或显式指定 ASC:

SELECT o_orderkey, o_orderdate, o_totalpriceFROM ordersORDER BY o_orderdate ASC;

十四、降序排序

查询账户余额最高的客户:

SELECT c_custkey, c_name, c_acctbalFROM customerORDER BY c_acctbal DESC;

查询最近的订单:

SELECT o_orderkey, o_orderdate, o_totalpriceFROM ordersORDER BY o_orderdate DESC;

十五、多列排序

可以按多个列进行排序,优先级从左到右:

SELECT o_orderkey, o_orderdate, o_totalprice, o_orderpriorityFROM ordersORDER 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_totalpriceFROM ordersORDER BY o_orderdate DESC, o_totalprice DESC;

通过 EXPLAIN 查看执行计划:

EXPLAIN SELECT o_orderkey, o_orderdate, o_totalpriceFROM ordersORDER BY o_orderdate DESC;

如果执行计划中没有 Using filesort,说明使用了索引排序,性能最优。

十七、限制查询结果数量

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

十八、获取前 N 条记录

查询前10个最大金额的订单:

SELECT o_orderkey, o_orderdate, o_totalpriceFROM ordersORDER BY o_totalprice DESCLIMIT 10;

查询账户余额最高的前20名客户:

SELECT c_custkey, c_name, c_acctbalFROM customerORDER BY c_acctbal DESCLIMIT 20;

十九、分页查询

使用 LIMIT offset, count 或 LIMIT count OFFSET offset 进行分页:

方式一:

— 查询第 2 页数据(每页 20 条)SELECT c_custkey, c_name, c_acctbalFROM customerORDER BY c_custkeyLIMIT 20, 20; — offset=20, count=20

方式二(推荐):

— 更清晰的写法SELECT c_custkey, c_name, c_acctbalFROM customerORDER BY c_custkeyLIMIT 20 OFFSET 20;

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_totalpriceFROM ordersORDER BY o_totalprice DESC;– 扫描行数: 1,500,000 (全表)– 有 LIMIT:提前终止SELECT o_orderkey, o_totalpriceFROM ordersORDER BY o_totalprice DESCLIMIT 10;– 扫描行数: ~10(使用索引)或使用堆排序优化

21、分页优化建议

深度分页问题:

— 性能差:需要扫描并跳过前 1,000,000 行SELECT o_orderkey, o_orderdateFROM ordersORDER BY o_orderkeyLIMIT 1000000, 20;

优化方案:使用范围查询代替 OFFSET

— 方式一:记录上次查询的最大 IDSELECT o_orderkey, o_orderdateFROM ordersWHERE o_orderkey > 1000000 — 上次最后一条记录的 IDORDER BY o_orderkeyLIMIT 20;– 方式二:使用覆盖索引 + 延迟关联SELECT o.o_orderkey, o.o_orderdate, o.o_totalpriceFROM orders oINNER JOIN ( SELECT o_orderkey FROM orders ORDER BY o_orderkey LIMIT 1000000, 20) tmp ON o.o_orderkey = tmp.o_orderkey;

22、聚合查询

聚合查询用于对数据进行统计分析,常用的聚合函数包括 COUNT、SUM、AVG、MAX、MIN 等。

23、基础聚合函数

统计总订单数:

SELECT COUNT(*) AS total_ordersFROM orders;

统计总销售额:

SELECT SUM(o_totalprice) AS total_salesFROM orders;

查询最大和最小订单金额:

SELECT MAX(o_totalprice) AS max_order_amount, MIN(o_totalprice) AS min_order_amount, AVG(o_totalprice) AS avg_order_amountFROM orders;

24、分组聚合

使用 GROUP BY 对数据进行分组统计。

统计每个市场细分的客户数量:

SELECT c_mktsegment, COUNT(*) AS customer_countFROM customerGROUP BY c_mktsegmentORDER 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_amountFROM ordersGROUP BY YEAR(o_orderdate)ORDER BY order_year DESC;

统计每个订单状态的订单数量:

SELECT o_orderstatus, COUNT(*) AS status_count, SUM(o_totalprice) AS total_amountFROM ordersGROUP BY o_orderstatus;

25、HAVING 子句

HAVING 用于过滤分组后的结果(与 WHERE 过滤原始行不同)。

查询订单数量超过1000的客户:

SELECT o_custkey, COUNT(*) AS order_count, SUM(o_totalprice) AS total_spentFROM ordersGROUP BY o_custkeyHAVING COUNT(*) > 1000ORDER BY total_spent DESC;

查询平均订单金额大于10000的年份:

SELECT YEAR(o_orderdate) AS order_year, AVG(o_totalprice) AS avg_amountFROM ordersGROUP BY YEAR(o_orderdate)HAVING AVG(o_totalprice) > 10000ORDER BY order_year;

26、去重统计

使用 DISTINCT 进行去重统计:

统计不同市场细分的数量:

SELECT COUNT(DISTINCT c_mktsegment) AS segment_countFROM customer;

统计有订单的客户数量:

SELECT COUNT(DISTINCT o_custkey) AS active_customersFROM orders;

27、聚合查询优化

TDSQL Boundless 聚合查询优化要点:

1. 索引加速分组:

— 在 GROUP BY 列上建立索引CREATE INDEX idx_mktsegment ON customer(c_mktsegment);– 此查询可以利用索引加速分组SELECT c_mktsegment, COUNT(*)FROM customerGROUP 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_salesFROM ordersGROUP BY YEAR(o_orderdate);

4. 分区表加速:

·如果表按日期分区,聚合查询可以并行在各分区上执行。

·TDSQL Boundless 会自动进行分区裁剪,只扫描相关分区。

— 假设 orders 表按年份分区– 此查询只扫描 1995 年的分区SELECT COUNT(*) AS order_count, SUM(o_totalprice) AS total_salesFROM ordersWHERE o_orderdate BETWEEN '1995-01-01' AND '1995-12-31';

赞 (0)
上一篇 4天前
下一篇 4天前