t-sql - sybase - 除非字符串是硬编码的,否则无法使用索引

标签 t-sql database-performance sap-ase

我正在使用Sybase 12.5.3 (ASE);尽管我已经广泛使用过 MSSQL,但我还是 Sybase 的新手。我遇到了存储过程确实非常慢的情况。我已将问题追溯到相对较大的表的单个 SELECT stmt。修改该语句极大地提高了过程的性能(并且恢复它会大大减慢速度;即 SELECT stmt 绝对是罪魁祸首)。

-- Sybase optimizes and uses multi-column index... fast!<br>
SELECT ID,status,dateTime
FROM myTable
WHERE status in ('NEW','SENT')
ORDER BY ID

-- Sybase does not use index and does very slow table scan<br>
SELECT ID,status,dateTime
FROM myTable
WHERE status in (select status from allowableStatusValues)
ORDER BY ID

上面的代码是实际代码的改编/简化版本。请注意,我已经尝试过重新编译程序、更新统计信息等。

我不知道为什么 Sybase ASE 仅在字符串硬编码时才选择索引,而在从另一个表中选择时选择表扫描。请有人给我一个线索,提前谢谢你。

最佳答案

1.这里的问题是编码不良。在您的版本中,糟糕的代码和糟糕的表设计是优化器做出错误决策的主要原因(98%)(两者是相辅相成的,我还没有弄清楚各自的比例)。两者:

    WHERE status IN ('NEW','SENT')

    WHERE status IN (SELECT status FROM allowableStatusValues)

不符合标准,因为在这两种情况下,它们都会导致 ASE 为括号之间的内容创建一个工作表,这很容易避免(并且可以避免所有随之而来的问题)。工作表上不可能有统计信息,因为 t.status 或 s.status 上的统计信息丢失(AdamH 在这一点上是正确的),它正确地选择了表扫描。

子查询有其用武之地,但永远不能替代纯连接(表相关)。更正如下:

    WHERE status = "NEW" OR status = "SENT"

    FROM  myTable t,
          allowableStatusValues s
    WHERE t.status = s.status

2.声明

|现在您不必添加索引来获取列的统计信息,但这可能是最好的方法。

不正确。切勿创建您不会使用的索引。如果您想更新列上的统计信息,只需

    UPDATE STATISTICS myTable (status)

3.确保您拥有 (a) 所有索引列和 (b) 所有联接列的最新统计信息非常重要。

4.是的,在每个要发​​布的代码段上,SHOWPLAN 是不可替代的,对于任何性能有问题的代码来说更是如此。您还可以SET NOEXEC ON,以避免执行,例如。对于大型结果集。

关于t-sql - sybase - 除非字符串是硬编码的,否则无法使用索引,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2501825/

相关文章:

sql - SQL Server 2005数据库中的新触发器

sql-server - 更新长度 > 50 的行

sql-server - 非规范化访问 : views or materialized tables?

mysql - BCP 以utf8文本文件转表

sql-server - 创建临时表并同时存储执行命令的结果

sql - SQL Server 中的嵌套表类型

sql-server - 如果值相同,SQL Server 是否足够聪明,不会更新?

database - 如何让Greenplum 4.2.3只扫描指定分区?

sql - 我可以告诉 MS SQL Server 忽略 Msg 8144(指定的参数太多)吗?

python - 使用 Python 到 SYBASE ASE 的 ODBC 连接