分类目录归档:未分类

MySQL 长度较大的VARCHAR索引限制说明

我来为您详细说明 MySQL 中长度较大的 VARCHAR 字段的索引限制问题。

MySQL VARCHAR 索引限制说明

1. 核心限制规则

MySQL 对索引长度有以下主要限制:

InnoDB 存储引擎

  • 最大索引长度: 767 字节 (MySQL 5.6 及更早版本)
  • 最大索引长度: 3072 字节 (MySQL 5.7+, 需启用 innodb_large_prefix)
  • 行格式要求: 必须使用 DYNAMICCOMPRESSED 行格式

MyISAM 存储引擎

  • 最大索引长度: 1000 字节

2. 字符集对索引长度的影响

不同字符集下,VARCHAR 字段能创建的最大索引长度不同:

单字节字符集 (latin1):
  - 767 字节限制:VARCHAR(767)
  - 3072 字节限制:VARCHAR(3072)

多字节字符集 (utf8mb4):
  - 每个字符最多 4 字节
  - 767 字节限制:VARCHAR(191)  [767 ÷ 4 = 191.75]
  - 3072 字节限制:VARCHAR(768)  [3072 ÷ 4 = 768]

3. 实际应用场景

问题场景

-- ❌ 在 utf8mb4 字符集下会报错
CREATE TABLE users (
    name VARCHAR(500),
    INDEX idx_name (name)  -- 错误:索引长度 2000 字节 > 767 字节
);

-- ✅ 安全的做法
CREATE TABLE users (
    name VARCHAR(191),
    INDEX idx_name (name)  -- 正确:191 × 4 = 764 字节 < 767 字节
);

解决方案

方案 1: 使用前缀索引

-- 只对字段的前 N 个字符创建索引
CREATE TABLE articles (
    title VARCHAR(500),
    INDEX idx_title_prefix (title(191))  -- 只索引前 191 个字符
);

方案 2: 升级配置 (MySQL 5.7+)

-- 1. 设置 innodb_large_prefix
SET GLOBAL innodb_large_prefix = ON;

-- 2. 使用 DYNAMIC 行格式
CREATE TABLE users (
    name VARCHAR(500),
    INDEX idx_name (name)
) ROW_FORMAT=DYNAMIC;

-- 3. 或者修改现有表
ALTER TABLE users ROW_FORMAT=DYNAMIC;

方案 3: 使用全文索引 (适合长文本搜索)

CREATE TABLE articles (
    content TEXT,
    FULLTEXT INDEX ft_content (content)
);

4. 查看当前配置

-- 查看 innodb_large_prefix 设置
SHOW VARIABLES LIKE 'innodb_large_prefix';

-- 查看表的行格式
SHOW TABLE STATUS LIKE 'your_table_name';

-- 查看数据库字符集
SHOW VARIABLES LIKE 'character_set_database';

-- 查看索引长度限制
SHOW VARIABLES LIKE 'innodb_default_row_format';

5. 最佳实践建议

  1. 推荐长度: 在 utf8mb4 字符集下,VARCHAR 索引字段最好不超过 191 个字符
  2. 前缀索引: 对于较长的字段,使用前缀索引可以平衡性能和空间
  3. 避免过度索引: 过长的索引会占用更多存储空间,降低写入性能
  4. 考虑替代方案:
    • 使用哈希索引 (适合精确匹配)
    • 使用全文索引 (适合模糊搜索)
    • 使用外部搜索引擎 (如 Elasticsearch)

6. 常见错误示例

Error 1071: Specified key was too long; max key length is 767 bytes
Error 1170: BLOB/TEXT column 'xxx' used in key specification without a key length

如果您需要针对具体的业务场景选择合适的索引策略,请告诉我您的具体需求(如字段用途、查询模式等),我可以给出更精准的建议。

MySQL 索引核心知识点总结

MySQL 索引核心知识点总结

一、索引基本概念

  • 定义:索引是帮助 MySQL 高效获取数据的数据结构(如 B+树、Hash),通过减少磁盘 I/O 次数提升查询效率‌。
  • 类比:类似于书籍的目录,通过快速定位数据行实现高效检索‌。
  • 存储引擎差异
    • InnoDB/MyISAM 默认使用 B+树索引‌。
    • Memory 引擎使用 Hash 索引(仅支持等值查询)‌。

二、索引类型

  1. 按功能分类
    • 主键索引(PRIMARY KEY):唯一且非空,InnoDB 中为聚簇索引(数据与索引存储在一起)‌。
    • 唯一索引(UNIQUE):列值唯一,允许空值‌。
    • 普通索引(INDEX):无唯一性限制,仅加速查询‌。
    • 复合索引:包含多列,需遵循最左前缀匹配原则‌。
    • 全文索引(FULLTEXT):适用于文本类型字段的模糊匹配(如 LIKE '%keyword%')‌。
    • 前缀索引:对文本字段前 N 个字符建立索引,节省空间‌。
  2. 按存储结构分类
    • 聚簇索引:数据行与索引存储在一起(如 InnoDB 主键索引)‌。
    • 非聚簇索引:索引与数据行分离(如 MyISAM 索引)‌17

三、索引的优缺点

  • 优点
    • 降低查询的 I/O 成本,提升检索效率‌。
    • 减少排序和分组操作的 CPU 消耗‌。
  • 缺点
    • 占用额外磁盘空间,索引文件可能比数据文件更大‌。
    • 增删改操作需维护索引,降低写性能‌。

四、索引底层结构(B+树)

  • 特点
    • 多路平衡搜索树,树高度低,适合磁盘存储‌。
    • 叶子节点存储实际数据或主键值(非聚簇索引需回表查询)‌。
    • 支持范围查询和排序操作‌。

五、索引失效场景

  1. 违反最左前缀法则:复合索引未从第一列开始使用‌。
    • 例:索引 (a, b, c),查询条件为 b=1 或 c=1 时失效。
  2. 范围查询右侧列失效:范围查询后的索引列无法使用‌。
    • 例:索引 (a, b),条件 a>1 AND b=2 中 b 可能失效。
  3. 对索引列进行运算或函数操作:如 WHERE YEAR(date_column)=2025‌。
  4. 头部模糊匹配:如 LIKE '%abc'‌。
  5. OR 连接非索引列:若 OR 条件中包含未索引字段,全表扫描‌。
  6. 隐式类型转换:如字符串字段未加引号(WHERE id='123' vs WHERE id=123)‌。

六、使用建议

  1. 适用场景
    • 频繁作为查询条件的字段(WHERE、JOIN)。
    • 需要排序或分组的字段(ORDER BY、GROUP BY)。
  2. 避免滥用
    • 数据量小的表无需索引。
    • 频繁更新的字段谨慎建索引。
  3. 优化策略
    • 优先选择区分度高的字段(如唯一性高的列)。
    • 控制复合索引的列数(一般不超过 5 列)‌。
    • 定期分析慢查询,调整索引策略‌。

七、操作语法示例

sqlCopy Code-- 创建索引  
CREATE INDEX idx_name ON table_name(column1, column2);  
-- 查看索引  
SHOW INDEX FROM table_name;  
-- 删除索引  
DROP INDEX idx_name ON table_name;

solr去重

配置文件:solrconfig.xml

<requestHandler name="/update" class="solr.UpdateRequestHandler" >
  <lst name="defaults">
    <str name="update.chain">dedupe</str>
  </lst>
</requestHandler>

<updateRequestProcessorChain name="dedupe">
  <processor class="solr.processor.SignatureUpdateProcessorFactory">
    <bool name="enabled">true</bool>
    <str name="signatureField">id</str>
    <bool name="overwriteDupes">true</bool>
    <str name="fields">object_id,object_type</str>
    <str name="signatureClass">solr.processor.Lookup3Signature</str>
  </processor>
  <processor class="solr.LogUpdateProcessorFactory" />
  <processor class="solr.RunUpdateProcessorFactory" />
</updateRequestProcessorChain>

修改fields字段为需要去重的字段

Arm64 Centos docker 启动 solr 问题解决方法

 docker container run -itd --name solr -e SOLR_JAVA_STACK_SIZE=-Xss1m solr -m 2g

指定SOLR_JAVA_STACK_SIZE即可

Starting Solr
Java 17 detected. Enabled workaround for SOLR-16463
[0.001s][warning][pagesize] UseLargePages disabled, no large pages configured and available on the system.

The Java thread stack size specified is too small. Specify at least 448k
Error: Could not create the Java Virtual Machine.
Error: A fatal exception has occurred. Program will exit.

CSS实现表格对角线

        td {
            background-size: 100% 100%;
            background-image: url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTAwJSIgaGVpZ2h0PSIxMDAlIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPg0KICA8bGluZSB4MT0iMCIgeTE9IjAiIHgyPSIxMDAlIiB5Mj0iMTAwJSIgc3Ryb2tlPSJibGFjayIgLz4NCjwvc3ZnPg==");
        }

net.ipv4.tcp_tw_reuse = 2 啥意思?

index 924bd51327b7..6841c74eac00 100644
--- a/[Documentation/networking/ip-sysctl.txt](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/Documentation/networking/ip-sysctl.txt?id=39dbc646fd2c67ee9b71450ce172cbd714d4e7fb)
+++ b/[Documentation/networking/ip-sysctl.txt](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/Documentation/networking/ip-sysctl.txt?id=79e9fed460385a3d8ba0b5782e9e74405cb199b1)
@@ -667,11 +667,15 @@ tcp_tso_win_divisor - INTEGER
building larger TSO frames.
Default: 3
-tcp_tw_reuse - BOOLEAN
- Allow to reuse TIME-WAIT sockets for new connections when it is
- safe from protocol viewpoint. Default value is 0.
+tcp_tw_reuse - INTEGER
+ Enable reuse of TIME-WAIT sockets for new connections when it is
+ safe from protocol viewpoint.
+ 0 - disable
+ 1 - global enable
+ 2 - enable for loopback traffic only
It should not be changed without advice/request of technical
experts.
+ Default: 2```

Much appreciated!

PHP生成器递归遍历目录

    private function fullScanDir($dir): \Generator
    {
        $list = scandir($dir);
        foreach ($list as $filename) {
            if ($filename === '.' || $filename === '..') continue;
            if ($filename === '.git') continue;
            $aDir = sprintf("%s/%s", $dir, $filename);
            if (is_dir($aDir)) {
                foreach ($this->fullScanDir($aDir) as $_filename) {
                    yield $_filename;
                }
            } else {
                yield $aDir;
            }
        }
    }